library(here)
library(tidyverse)
library(ggpubr)
library(epitools)
library(seqinr)
library(dplyr)
pal2 <- c("#015b58", "#5962b5")
pal2.flip <- c("#5962b5", "#015b58")
here::here()
[1] "/Users/emma/Library/CloudStorage/OneDrive-SharedLibraries-IndianaUniversity/Lennon, Jay - 0000_Bueren/Projects/LifeStyle/PhageLifestyleSporulation"
source(here("utility-scripts/cd-hit-cluster.R"))

box <- read.delim2(here("data/inphared_db/14Apr2025inph_0A_v3.txt" ))
## remove extra .txt headers from catting files
box <- subset(box, box$Context!="Context")
### remove incomplete flanking regions
box <- subset(box, box$Partial=="None")

box <- box %>% rename(product = Sequence, phage = Contig)
box[,c(2)] <- "0A"
#box <- box[,c(3,2,1)]
box$count <- 1


## FJ230960 spo1
## EU771092 phi29
## EU622808 nf
## KY030782 phi3t
## AF020713

if i needed to do reverse complement, don’t right now

box\(RevComp <- sapply(box\)Context, function(s) { c2s(rev(comp(s2c(s), forceToLower = FALSE))) })

box\(Five2Three <- ifelse(box\)Strand==“+”, box\(Context, box\)RevComp)

box.all <- box

phage <- read.csv(here("data/inphared_db/14Apr2025_knownsporestatus.csv"), row.names=1)




all <- merge(box, phage, by.x="phage", by.y="Accession", all.x=FALSE, all.y=TRUE) 

all$product[is.na(all$product)] <- "No_0A"

all.hits <- subset(all, all$product=="0A")


all.hits$strand2 <- ifelse(all.hits$Strand=="+", "Fwd", "Rev")

all.hits <- unite(all.hits, "Box_Contig", c("phage", "product", "strand2", "Position"), sep = "_", remove = FALSE, na.rm = FALSE)


all.hits[] <- lapply(all.hits, function(x) {
  if (is.character(x)) {
    gsub("Desulfobacterota_I", "Desulfobacterota", x)
  } else {
    x
  }
})

all.hits[] <- lapply(all.hits, function(x) {
  if (is.character(x)) {
    gsub("Bacteroidota_A", "Bacteroidota", x)
  } else {
    x
  }
})

all.hits[] <- lapply(all.hits, function(x) {
  if (is.character(x)) {
    gsub("Bacillaceae_C", "Bacillaceae", x)
  } else {
    x
  }
})

all.hits[] <- lapply(all.hits, function(x) {
  if (is.character(x)) {
    gsub("Bacillaceae_C", "Bacillaceae", x)
  } else {
    x
  }
})

all.hits[] <- lapply(all.hits, function(x) {
  if (is.character(x)) {
    gsub("Bacillales_D", "Bacillales", x)
  } else {
    x
  }
})

all.hits[] <- lapply(all.hits, function(x) {
  if (is.character(x)) {
    gsub("Bacillales_A", "Bacillales", x)
  } else {
    x
  }
})

all.hits[] <- lapply(all.hits, function(x) {
  if (is.character(x)) {
    gsub("Bacillales_B", "Bacillales", x)
  } else {
    x
  }
})



# Construct FASTA-formatted lines
fasta_lines <- paste0(">", all.hits$Box_Contig, "\n", all.hits$Context_no_motif)
#fasta_lines
# Write to file
writeLines(fasta_lines, here("data/inphared_db/14Apr2025_0Ahits_nopartials.fna"))
           
           
           
clust <- read.csv(here("data/inphared_db/0a_clusters/nested/14Apr2025_0A_nested.csv"), row.names=1)

library(DECIPHER)
set.seed(123)
# specify the path to the FASTA file (in quotes)
fas <- here("data/inphared_db/0a_clusters/nested/14Apr2025_0A_80sim.out")

# load the sequences from the file
# change "DNA" to "RNA" or "AA" as needed
seqs <- readDNAStringSet(fas)




clust.50 <- Clusterize(seqs,
cutoff=0.5, # > 50% similar
minCoverage=0.5, # > 50% coverage
processors=NULL) # use all CPUs
Partitioning sequences by 8-mer similarity:

  |                                                                                         
  |                                                                                   |   0%
  |                                                                                         
  |=                                                                                  |   1%
  |                                                                                         
  |==                                                                                 |   2%
  |                                                                                         
  |==                                                                                 |   3%
  |                                                                                         
  |===                                                                                |   4%
  |                                                                                         
  |====                                                                               |   5%
  |                                                                                         
  |=====                                                                              |   6%
  |                                                                                         
  |======                                                                             |   7%
  |                                                                                         
  |=======                                                                            |   8%
  |                                                                                         
  |=======                                                                            |   9%
  |                                                                                         
  |========                                                                           |  10%
  |                                                                                         
  |=========                                                                          |  11%
  |                                                                                         
  |==========                                                                         |  12%
  |                                                                                         
  |===========                                                                        |  13%
  |                                                                                         
  |============                                                                       |  14%
  |                                                                                         
  |============                                                                       |  15%
  |                                                                                         
  |=============                                                                      |  16%
  |                                                                                         
  |==============                                                                     |  17%
  |                                                                                         
  |===============                                                                    |  18%
  |                                                                                         
  |================                                                                   |  19%
  |                                                                                         
  |=================                                                                  |  20%
  |                                                                                         
  |=================                                                                  |  21%
  |                                                                                         
  |==================                                                                 |  22%
  |                                                                                         
  |===================                                                                |  23%
  |                                                                                         
  |====================                                                               |  24%
  |                                                                                         
  |=====================                                                              |  25%
  |                                                                                         
  |======================                                                             |  26%
  |                                                                                         
  |======================                                                             |  27%
  |                                                                                         
  |=======================                                                            |  28%
  |                                                                                         
  |========================                                                           |  29%
  |                                                                                         
  |=========================                                                          |  30%
  |                                                                                         
  |==========================                                                         |  31%
  |                                                                                         
  |===========================                                                        |  32%
  |                                                                                         
  |===========================                                                        |  33%
  |                                                                                         
  |============================                                                       |  34%
  |                                                                                         
  |=============================                                                      |  35%
  |                                                                                         
  |==============================                                                     |  36%
  |                                                                                         
  |===============================                                                    |  37%
  |                                                                                         
  |================================                                                   |  38%
  |                                                                                         
  |================================                                                   |  39%
  |                                                                                         
  |=================================                                                  |  40%
  |                                                                                         
  |==================================                                                 |  41%
  |                                                                                         
  |===================================                                                |  42%
  |                                                                                         
  |====================================                                               |  43%
  |                                                                                         
  |=====================================                                              |  44%
  |                                                                                         
  |=====================================                                              |  45%
  |                                                                                         
  |======================================                                             |  46%
  |                                                                                         
  |=======================================                                            |  47%
  |                                                                                         
  |========================================                                           |  48%
  |                                                                                         
  |=========================================                                          |  49%
  |                                                                                         
  |==========================================                                         |  50%
  |                                                                                         
  |==========================================                                         |  51%
  |                                                                                         
  |===========================================                                        |  52%
  |                                                                                         
  |============================================                                       |  53%
  |                                                                                         
  |=============================================                                      |  54%
  |                                                                                         
  |==============================================                                     |  55%
  |                                                                                         
  |==============================================                                     |  56%
  |                                                                                         
  |===============================================                                    |  57%
  |                                                                                         
  |================================================                                   |  58%
  |                                                                                         
  |=================================================                                  |  59%
  |                                                                                         
  |==================================================                                 |  60%
  |                                                                                         
  |===================================================                                |  61%
  |                                                                                         
  |===================================================                                |  62%
  |                                                                                         
  |====================================================                               |  63%
  |                                                                                         
  |=====================================================                              |  64%
  |                                                                                         
  |======================================================                             |  65%
  |                                                                                         
  |=======================================================                            |  66%
  |                                                                                         
  |========================================================                           |  67%
  |                                                                                         
  |========================================================                           |  68%
  |                                                                                         
  |=========================================================                          |  69%
  |                                                                                         
  |==========================================================                         |  70%
  |                                                                                         
  |===========================================================                        |  71%
  |                                                                                         
  |============================================================                       |  72%
  |                                                                                         
  |=============================================================                      |  73%
  |                                                                                         
  |=============================================================                      |  74%
  |                                                                                         
  |==============================================================                     |  75%
  |                                                                                         
  |===============================================================                    |  76%
  |                                                                                         
  |================================================================                   |  77%
  |                                                                                         
  |=================================================================                  |  78%
  |                                                                                         
  |==================================================================                 |  79%
  |                                                                                         
  |==================================================================                 |  80%
  |                                                                                         
  |===================================================================                |  81%
  |                                                                                         
  |====================================================================               |  82%
  |                                                                                         
  |=====================================================================              |  83%
  |                                                                                         
  |======================================================================             |  84%
  |                                                                                         
  |=======================================================================            |  85%
  |                                                                                         
  |=======================================================================            |  86%
  |                                                                                         
  |========================================================================           |  87%
  |                                                                                         
  |=========================================================================          |  88%
  |                                                                                         
  |==========================================================================         |  89%
  |                                                                                         
  |===========================================================================        |  90%
  |                                                                                         
  |============================================================================       |  91%
  |                                                                                         
  |============================================================================       |  92%
  |                                                                                         
  |=============================================================================      |  93%
  |                                                                                         
  |==============================================================================     |  94%
  |                                                                                         
  |===============================================================================    |  95%
  |                                                                                         
  |================================================================================   |  96%
  |                                                                                         
  |=================================================================================  |  97%
  |                                                                                         
  |=================================================================================  |  98%
  |                                                                                         
  |================================================================================== |  99%
  |                                                                                         
  |===================================================================================| 100%

Time difference of 3.11 secs

Sorting by relatedness within 42412 groups:

iteration 1 of up to 4 (100.0% stability) 
iteration 1 of up to 4 (100.0% stability) 

Time difference of 0.55 secs

Clustering sequences by 7-mer similarity:

  |                                                                                         
  |                                                                                   |   0%
  |                                                                                         
  |=                                                                                  |   1%
  |                                                                                         
  |==                                                                                 |   2%
  |                                                                                         
  |==                                                                                 |   3%
  |                                                                                         
  |===                                                                                |   4%
  |                                                                                         
  |====                                                                               |   5%
  |                                                                                         
  |=====                                                                              |   6%
  |                                                                                         
  |======                                                                             |   7%
  |                                                                                         
  |=======                                                                            |   8%
  |                                                                                         
  |=======                                                                            |   9%
  |                                                                                         
  |========                                                                           |  10%
  |                                                                                         
  |=========                                                                          |  11%
  |                                                                                         
  |==========                                                                         |  12%
  |                                                                                         
  |===========                                                                        |  13%
  |                                                                                         
  |============                                                                       |  14%
  |                                                                                         
  |============                                                                       |  15%
  |                                                                                         
  |=============                                                                      |  16%
  |                                                                                         
  |==============                                                                     |  17%
  |                                                                                         
  |===============                                                                    |  18%
  |                                                                                         
  |================                                                                   |  19%
  |                                                                                         
  |=================                                                                  |  20%
  |                                                                                         
  |=================                                                                  |  21%
  |                                                                                         
  |==================                                                                 |  22%
  |                                                                                         
  |===================                                                                |  23%
  |                                                                                         
  |====================                                                               |  24%
  |                                                                                         
  |=====================                                                              |  25%
  |                                                                                         
  |======================                                                             |  26%
  |                                                                                         
  |======================                                                             |  27%
  |                                                                                         
  |=======================                                                            |  28%
  |                                                                                         
  |========================                                                           |  29%
  |                                                                                         
  |=========================                                                          |  30%
  |                                                                                         
  |==========================                                                         |  31%
  |                                                                                         
  |===========================                                                        |  32%
  |                                                                                         
  |===========================                                                        |  33%
  |                                                                                         
  |============================                                                       |  34%
  |                                                                                         
  |=============================                                                      |  35%
  |                                                                                         
  |==============================                                                     |  36%
  |                                                                                         
  |===============================                                                    |  37%
  |                                                                                         
  |================================                                                   |  38%
  |                                                                                         
  |================================                                                   |  39%
  |                                                                                         
  |=================================                                                  |  40%
  |                                                                                         
  |==================================                                                 |  41%
  |                                                                                         
  |===================================                                                |  42%
  |                                                                                         
  |====================================                                               |  43%
  |                                                                                         
  |=====================================                                              |  44%
  |                                                                                         
  |=====================================                                              |  45%
  |                                                                                         
  |======================================                                             |  46%
  |                                                                                         
  |=======================================                                            |  47%
  |                                                                                         
  |========================================                                           |  48%
  |                                                                                         
  |=========================================                                          |  49%
  |                                                                                         
  |==========================================                                         |  50%
  |                                                                                         
  |==========================================                                         |  51%
  |                                                                                         
  |===========================================                                        |  52%
  |                                                                                         
  |============================================                                       |  53%
  |                                                                                         
  |=============================================                                      |  54%
  |                                                                                         
  |==============================================                                     |  55%
  |                                                                                         
  |==============================================                                     |  56%
  |                                                                                         
  |===============================================                                    |  57%
  |                                                                                         
  |================================================                                   |  58%
  |                                                                                         
  |=================================================                                  |  59%
  |                                                                                         
  |==================================================                                 |  60%
  |                                                                                         
  |===================================================                                |  61%
  |                                                                                         
  |===================================================                                |  62%
  |                                                                                         
  |====================================================                               |  63%
  |                                                                                         
  |=====================================================                              |  64%
  |                                                                                         
  |======================================================                             |  65%
  |                                                                                         
  |=======================================================                            |  66%
  |                                                                                         
  |========================================================                           |  67%
  |                                                                                         
  |========================================================                           |  68%
  |                                                                                         
  |=========================================================                          |  69%
  |                                                                                         
  |==========================================================                         |  70%
  |                                                                                         
  |===========================================================                        |  71%
  |                                                                                         
  |============================================================                       |  72%
  |                                                                                         
  |=============================================================                      |  73%
  |                                                                                         
  |=============================================================                      |  74%
  |                                                                                         
  |==============================================================                     |  75%
  |                                                                                         
  |===============================================================                    |  76%
  |                                                                                         
  |================================================================                   |  77%
  |                                                                                         
  |=================================================================                  |  78%
  |                                                                                         
  |==================================================================                 |  79%
  |                                                                                         
  |==================================================================                 |  80%
  |                                                                                         
  |===================================================================                |  81%
  |                                                                                         
  |====================================================================               |  82%
  |                                                                                         
  |=====================================================================              |  83%
  |                                                                                         
  |======================================================================             |  84%
  |                                                                                         
  |=======================================================================            |  85%
  |                                                                                         
  |=======================================================================            |  86%
  |                                                                                         
  |========================================================================           |  87%
  |                                                                                         
  |=========================================================================          |  88%
  |                                                                                         
  |==========================================================================         |  89%
  |                                                                                         
  |===========================================================================        |  90%
  |                                                                                         
  |============================================================================       |  91%
  |                                                                                         
  |============================================================================       |  92%
  |                                                                                         
  |=============================================================================      |  93%
  |                                                                                         
  |==============================================================================     |  94%
  |                                                                                         
  |===============================================================================    |  95%
  |                                                                                         
  |================================================================================   |  96%
  |                                                                                         
  |=================================================================================  |  97%
  |                                                                                         
  |=================================================================================  |  98%
  |                                                                                         
  |================================================================================== |  99%
  |                                                                                         
  |===================================================================================| 100%

Time difference of 14.47 secs

Clusters via relatedness sorting: 100% (11.1% exclusively)
Clusters via rare 8-mers: 88.9% (0% exclusively)
Estimated clustering effectiveness: 100%
clust50 <- clust.50
clust50$Sequence_ID <- row.names(clust50)
clust50$cluster<- paste0("50_", clust50$cluster)

clust.super <- merge(clust, clust50, by="Sequence_ID", all=TRUE)
clust8050 <- unique(clust.super[,c(6:7)])
clust8050 <- na.omit(clust8050)
colnames(clust8050) <- c("Cluster80", "Cluster50")


clust <- merge(clust, clust8050, by="Cluster80", all=TRUE)

all.clust <- merge(all.hits, clust, by.x="Box_Contig", by.y="Sequence_ID", all.x=TRUE, all.y=TRUE)


gc_content <- function(seq) {
  seq <- toupper(seq)
  bases <- strsplit(seq, "")[[1]]
  gc_count <- sum(bases %in% c("G", "C"))
  total <- length(bases)
  return(gc_count / total)
}

# Vectorized version for multiple sequences
gc_content_vec <- function(seqs) {
  sapply(seqs, gc_content)
}


all.clust$GC.flanks <- gc_content_vec(all.clust$Upstream)


gc.check <- select(all.clust, phage, GC.flanks, Context, Context_no_motif, gtdb_f, f_spor, predicted_label, host_phage_spor, phage_type, sporulation, newgtdb_Phylum, host_phyla, lifestyle,)



gc.check.mean.nofilt <- gc.check %>%
  group_by(host_phage_spor) %>%
  summarise(gc_mean = mean(GC.flanks), total=n())

#gc.check <- subset(gc.check, gc.check$GC.flanks<0.35)

gc.check.mean <- gc.check %>%
  group_by(host_phage_spor) %>%
  summarise(gc_mean = mean(GC.flanks), total=n())


all.clust.clean <- all.clust

all.clust <- subset(all.clust.clean, all.clust.clean$GC.flanks<0.35)
host.clust <- all.clust %>%
  group_by(Cluster50, Host) %>%
  summarise(n = n()) %>%
  arrange(desc(n))
`summarise()` has grouped output by 'Cluster50'. You can override using the `.groups` argument.
cluster_super.matrix <- all.clust %>%
  group_by(Cluster50, hostspec_phage_spor) %>%
  summarise(count = n(), .groups = "drop") %>%
  pivot_wider(names_from = hostspec_phage_spor, values_from = count, values_fill = 0) %>%
  column_to_rownames("Cluster50") %>%
  as.matrix()

t.super <- t(cluster_super.matrix)

cluster_taxa_matrix <- all.clust %>%
  group_by(Cluster50, host_phage_spor) %>%
  summarise(count = n(), .groups = "drop") %>%
  pivot_wider(names_from = host_phage_spor, values_from = count, values_fill = 0) %>%
  column_to_rownames("Cluster50") %>%
  as.matrix()

t.all <- t(cluster_taxa_matrix)

#all.clust.bacill <- subset(all.clust, all.clust$newgtdb_Phylum=="Bacillota" | all.clust$newgtdb_Phylum=="Pseudomonadota")

all.clust.bacill <- subset(all.clust, all.clust$newgtdb_Phylum=="Bacillota")

cluster_taxa_matrix <- all.clust.bacill %>%
  group_by(Cluster50, phage_type) %>%
  summarise(count = n(), .groups = "drop") %>%
  pivot_wider(names_from = phage_type, values_from = count, values_fill = 0) %>%
  column_to_rownames("Cluster50") %>%
  as.matrix()

t.bacilli <- t(cluster_taxa_matrix)


cluster_taxa_matrix <- all.clust.bacill %>%
  group_by(Cluster50, phage) %>%
  summarise(count = n(), .groups = "drop") %>%
  pivot_wider(names_from = phage, values_from = count, values_fill = 0) %>%
  column_to_rownames("Cluster50") %>%
  as.matrix()

all.clust.bacill <- unite(all.clust.bacill, "fam_life", c("gtdb_f", "lifestyle"), sep = "_", remove = FALSE, na.rm = FALSE)


cluster_fam_matrix <- all.clust.bacill %>%
  group_by(Cluster50, fam_life) %>%
  summarise(count = n(), .groups = "drop") %>%
  pivot_wider(names_from = fam_life, values_from = count, values_fill = 0) %>%
  column_to_rownames("Cluster50") %>%
  as.matrix()

t.bacilli.fam <- t(cluster_fam_matrix)

library(pheatmap)

pheatmap(t.all,
         cluster_rows = TRUE,
         cluster_cols = TRUE,
         display_numbers = TRUE,
         fontsize = 10,
         main = "Taxonomic Composition by Flanking Sequence Cluster")



pheatmap(t.bacilli,
         cluster_rows = TRUE,
         cluster_cols = TRUE,
         display_numbers = TRUE,
         fontsize = 10,
         main = "Taxonomic Composition by Flanking Sequence Cluster")


pheatmap(t.bacilli.fam,
         cluster_rows = TRUE,
         cluster_cols = TRUE,
         display_numbers = TRUE,
         fontsize = 10,
         main = "Taxonomic Composition by Flanking Sequence Cluster")




library(vegan)
library(ggplot2)




bray_dist.bac <- vegdist(t.bacilli, method = "bray")
jaccard_dist.bac <- vegdist(t.bacilli, method = "jaccard")



hc.jac.bac <- hclust(jaccard_dist.bac, method = "ward.D")  # Use "complete", "ward.D", etc. if preferred
plot(hc.jac.bac, main = "Ward.D Clustering of 0A Flanks in Phages by Host",
     xlab = "Cluster", sub = "", hang = -1)



hc.bray.bac <- hclust(bray_dist.bac, method = "ward.D")  # Use "complete", "ward.D", etc. if preferred
plot(hc.bray.bac, main = "Dendrogram of Flanking Clusters by Host Composition",
     xlab = "Cluster", sub = "", hang = -1)





bray_dist.all <- vegdist(t.all, method = "bray")
jaccard_dist.all <- vegdist(t.all, method = "jaccard")


hc.bray.all <- hclust(bray_dist.all, method = "ward.D")  # Use "complete", "ward.D", etc. if preferred
plot(hc.bray.all, main = "Dendrogram of Flanking Clusters by Host Composition",
     xlab = "Cluster", sub = "", hang = -1)

hc.dist.all <- hclust(jaccard_dist.all, method = "ward.D")  # Use "complete", "ward.D", etc. if preferred
par(mar = c(5, 8, 4, 15))  # adjust as needed

plot(as.dendrogram(hc.dist.all),
     main = "Ward.D Clustering of 0A Flanks in Phages by Host",
     xlab = "Height", ylab = "Cluster",
     sub = "", horiz = TRUE)


ggsave(here("lab_pres/Ward_BacVsOther0A_jacc.png"))
Saving 7.29 x 4.51 in image

bray_dist.phy <- vegdist(t.super, method = "bray")
jaccard_dist.phy <- vegdist(t.super, method = "jaccard")

hc.bray.phy <- hclust(bray_dist.phy, method = "ward.D")  # Use "complete", "ward.D", etc. if preferred
plot(hc.bray.phy, main = "Dendrogram of Flanking Clusters by Host Composition",
     xlab = "Cluster", sub = "", hang = -1)


hc.dist.phy <- hclust(jaccard_dist.phy, method = "ward.D")  # Use "complete", "ward.D", etc. if preferred
plot(hc.dist.phy, main = "Ward.D Clustering of 0A Flanks in Phages by Host",
     xlab = "Cluster", sub = "", hang = -1)


ggsave(here("lab_pres/Ward_Phy0A_jacc.png"))
Saving 7.29 x 4.51 in image
jaccard_dist.fam <- vegdist(t.bacilli.fam, method = "jaccard")
hc.dist.phy <- hclust(jaccard_dist.fam, method = "ward.D")  # Use "complete", "ward.D", etc. if preferred
par(mar = c(5, 8, 4, 15))  # adjust as needed


# Then plot your dendrogram
plot(as.dendrogram(hc.dist.phy),
     main = "Ward.D Clustering of 0A Flanks in Phages by Host",
     xlab = "Height", ylab = "Cluster",
     sub = "", horiz = TRUE)

library(dendextend)


jaccard_dist.fam <- vegdist(t.bacilli.fam, method = "jaccard")
hc.dist.phy <- hclust(jaccard_dist.fam, method = "ward.D")  # Use "complete", "ward.D", etc. if preferred
par(mar = c(5, 8, 4, 15))  # adjust as needed

# Then plot your dendrogram
plot(as.dendrogram(hc.dist.phy),
     main = "Ward.D Clustering of 0A Flanks in Phages by Host",
     xlab = "Height", ylab = "Cluster",
     sub = "", horiz = TRUE)


# 2. Convert to dendrogram object
dend <- as.dendrogram(hc.dist.phy)



meta <- select(all.clust.bacill, hostspec_phage_spor, sporulation, lifestyle, host_phyla,newgtdb_Phylum, fam_life, gtdb_f)
meta <- unique(meta)
rownames(meta) <- meta$fam_life

# Ensure rownames of meta are fam_life, which match dend labels
rownames(meta) <- meta$fam_life
group_vector <- meta$gtdb_f
names(group_vector) <- meta$fam_life
label_order <- labels(dend)
group_vector <- group_vector[label_order]

library(dendextend)


library(viridis)
palette <- turbo(length(unique(group_vector)))

# Same as above
tip_colors <- setNames(palette, levels(as.factor(group_vector)))[group_vector]

dend_colored <- dend %>%
  set("labels_colors", value = tip_colors)

par(mar = c(5, 8, 4, 15))

plot(dend_colored, main = "Clustered by fam_life, Colored by GTDB Family", horiz = TRUE)

legend("topright", legend = unique(group_vector),
       fill = as.numeric(as.factor(unique(group_vector))), border = NA, bty = "n")



# 4. Color the branches or labels
dend_colored <- dend %>%
  set("labels_colors", value = as.numeric(as.factor(group_vector)))# %>%
  #set("branches_k_color", k = length(unique(group_vector)))  # optional


par(mar = c(5, 8, 4, 15))  # adjust as needed

plot(as.dendrogram(dend_colored),
     main = "Ward.D Clustering of 0A Flanks in Phages by Host",
     xlab = "Height", ylab = "Cluster",
     sub = "", horiz = TRUE)

library(dendextend)
all.clust.bacill <- subset(all.clust, all.clust$newgtdb_Phylum=="Bacillota")
all.clust.bacill <- unite(all.clust.bacill, "ord_life", c("newgtdb_Order", "lifestyle", "sporulation"), sep = "_", remove = FALSE, na.rm = FALSE)


cluster_order_matrix <- all.clust.bacill %>%
  group_by(Cluster50, ord_life) %>%
  summarise(count = n(), .groups = "drop") %>%
  pivot_wider(names_from = ord_life, values_from = count, values_fill = 0) %>%
  column_to_rownames("Cluster50") %>%
  as.matrix()

t.bacilli.ord <- t(cluster_order_matrix)



jaccard_dist.ord <- vegdist(t.bacilli.ord, method = "jaccard")
hc.dist.phy <- hclust(jaccard_dist.ord, method = "ward.D")  # Use "complete", "ward.D", etc. if preferred
par(mar = c(5, 8, 4, 15))  # adjust as needed

# Then plot your dendrogram
plot(as.dendrogram(hc.dist.phy),
     main = "Ward.D Clustering of 0A Flanks in Phages by Host",
     xlab = "Height", ylab = "Cluster",
     sub = "", horiz = TRUE)


# 2. Convert to dendrogram object
dend <- as.dendrogram(hc.dist.phy)



meta <- select(all.clust.bacill, hostspec_phage_spor, sporulation, lifestyle, host_phyla,newgtdb_Phylum, ord_life, newgtdb_Order)
meta <- unique(meta)
rownames(meta) <- meta$ord_life

# Ensure rownames of meta are fam_life, which match dend labels
rownames(meta) <- meta$ord_life
group_vector <- meta$newgtdb_Order
names(group_vector) <- meta$ord_life
label_order <- labels(dend)
group_vector <- group_vector[label_order]

library(dendextend)


library(viridis)
palette <- turbo(length(unique(group_vector)))

# Same as above
tip_colors <- setNames(palette, levels(as.factor(group_vector)))[group_vector]

dend_colored <- dend %>%
  set("labels_colors", value = tip_colors)

par(mar = c(5, 8, 4, 15))

plot(dend_colored, main = "Clustered by ord_life, Colored by GTDB Family", horiz = TRUE)

legend("topright", legend = unique(group_vector),
       fill = as.numeric(as.factor(unique(group_vector))), border = NA, bty = "n")



# 4. Color the branches or labels
dend_colored <- dend %>%
  set("labels_colors", value = as.numeric(as.factor(group_vector)))# %>%
  #set("branches_k_color", k = length(unique(group_vector)))  # optional


par(mar = c(5, 8, 4, 15))  # adjust as needed

plot(as.dendrogram(dend_colored),
     main = "Ward.D Clustering of 0A Flanks in Phages by Host",
     xlab = "Height", ylab = "Cluster",
     sub = "", horiz = TRUE)

library(vegan)
library(ggplot2)

# 1. Compute Bray-Curtis distance
bray_dist.phy <- vegdist(t.bacilli.fam, method = "bray")

# 2. Run NMDS
nmds_result <- metaMDS(bray_dist.phy, k = 2, trymax = 100)

# 3. Extract NMDS coordinates
nmds_points <- as.data.frame(nmds_result$points)
nmds_points$SampleID <- rownames(nmds_points)


meta <- select(all.clust.bacill, hostspec_phage_spor, fam_life, sporulation, lifestyle, host_phyla,newgtdb_Phylum, gtdb_f, phage_type, newgtdb_Order, newgtdb_Class)

meta <- subset(meta, meta$newgtdb_Phylum=="Bacillota")
meta <- unique(meta)

# 4. If you have metadata (e.g., groupings), merge it here
# Assuming `meta` is a data.frame with sample metadata and matching rownames
 nmds_points <- merge(nmds_points, meta, by.x = "SampleID", by.y = "fam_life")

# 5. Plot
ggplot(nmds_points, aes(x = MDS1, y = MDS2, color= newgtdb_Order, shape=sporulation)) +
  geom_point(size = 3) +
  theme_minimal() +
  labs(title = "NMDS of Bray-Curtis Distances", x = "NMDS1", y = "NMDS2") 
 
 
ggplot(nmds_points, aes(x = MDS1, y = MDS2, color= newgtdb_Order, shape=phage_type)) +
  geom_point(size = 4) +
  theme_minimal() +
  labs(title = "NMDS of Jaccard Distances of 0A boxes of Bacillota phages", x = "NMDS1", y = "NMDS2")

#ggsave(here("lab_pres/Jaccard_0ABacilliota_NMDS.png"), height = 9, width=9)


ggplot(nmds_points, aes(x = MDS1, y = MDS2, color= newgtdb_Order, shape=phage_type)) +
  geom_point(size = 4) +
  theme_minimal() +
  labs(title = "NMDS of Bray Distances of 0A boxes of Bacillota phages", x = "NMDS1", y = "NMDS2")



ggsave(here("lab_pres/Bray_0ABacilliota_NMDS.png"), height = 9, width=9)
library(vegan)
library(ggplot2)

# 1. Compute Bray-Curtis distance
bray_dist.phy <- vegdist(t.super, method = "bray")

# 2. Run NMDS
nmds_result <- metaMDS(bray_dist.phy, k = 2, trymax = 100)

# 3. Extract NMDS coordinates
nmds_points <- as.data.frame(nmds_result$points)
nmds_points$SampleID <- rownames(nmds_points)


meta <- select(all, hostspec_phage_spor, sporulation, lifestyle, host_phyla,newgtdb_Phylum)
meta <- unique(meta)

# 4. If you have metadata (e.g., groupings), merge it here
# Assuming `meta` is a data.frame with sample metadata and matching rownames
 nmds_points <- merge(nmds_points, meta, by.x = "SampleID", by.y = "hostspec_phage_spor")

# 5. Plot
ggplot(nmds_points, aes(x = MDS1, y = MDS2, color=newgtdb_Phylum, shape=lifestyle)) +
  geom_point(size = 5) +
  theme_minimal() +
  labs(title = "NMDS of Bray-Curtis Distances", x = "NMDS1", y = "NMDS2")


ggsave(here("lab_pres/NMDS_Phy0A_bray.png"), height = 9, width=9)
library(vegan)
library(ggplot2)

# 1. Compute Bray-Curtis distance
bray_dist.phy <- vegdist(t.super, method = "jaccard")

# 2. Run NMDS
nmds_result <- metaMDS(bray_dist.phy, k = 2, trymax = 100)

# 3. Extract NMDS coordinates
nmds_points <- as.data.frame(nmds_result$points)
nmds_points$SampleID <- rownames(nmds_points)


meta <- select(all, hostspec_phage_spor, sporulation, lifestyle, host_phyla,newgtdb_Phylum)
meta <- unique(meta)

# 4. If you have metadata (e.g., groupings), merge it here
# Assuming `meta` is a data.frame with sample metadata and matching rownames
 nmds_points <- merge(nmds_points, meta, by.x = "SampleID", by.y = "hostspec_phage_spor")

# 5. Plot
ggplot(nmds_points, aes(x = MDS1, y = MDS2, color=newgtdb_Phylum, shape=lifestyle)) +
  geom_point(size = 5) +
  theme_minimal() +
  labs(title = "NMDS of Jaccard Distances", x = "NMDS1", y = "NMDS2")

ggsave(here("lab_pres/NMDS_Phy0A_jaccard.png"), height = 9, width=10)


library(phyloseq)

otu <- otu_table(t.super, taxa_are_rows = FALSE)

sample_names(otu)


sample_df <- phage

rownames(sample_df) <- sample_df$Accession
sample_data_obj <- sample_data(sample_df)



ps <- phyloseq(otu_table(otu), sample_data(sample_data_obj))


# Bray-Curtis
ord_bc <- ordinate(ps, method = "PCoA", distance = "bray")

# Jaccard (binary presence/absence)
ord_jaccard <- ordinate(ps, method = "PCoA", distance = "jaccard")


plot_ordination(ps, ord_bc, color="host_phage_spor") +
  ggtitle("PcOA (Bray-Curtis)") +
  theme_minimal()

plot_ordination(ps, ord_jaccard, color="newgtdb_Class") +
  ggtitle("PcOA (Bray-Curtis)") +
  theme_minimal()

library(phyloseq)

otu <- otu_table(t.bacilli.phage, taxa_are_rows = FALSE)

#sample_names(otu)

sample_df <- phage

rownames(sample_df) <- sample_df$Accession sample_data_obj <- sample_data(sample_df)

ps <- phyloseq(otu_table(otu), sample_data(sample_data_obj))

Bray-Curtis

ord_bc <- ordinate(ps, method = “PCoA”, distance = “bray”)

Jaccard (binary presence/absence)

ord_jaccard <- ordinate(ps, method = “PCoA”, distance = “jaccard”)

plot_ordination(ps, ord_bc, color=“host_phage_spor”) + ggtitle(“PcOA (Bray-Curtis)”) + theme_minimal()

plot_ordination(ps, ord_jaccard, color=“newgtdb_Class”) + ggtitle(“PcOA (Bray-Curtis)”) + theme_minimal()

MAYBE ALSO LOL IDK

unique.30 <- as.data.frame(unique(all.hits$Context))

unique.30\(boxID <- row.names(unique.30) colnames(unique.30) <- c("Context", "boxID") unique.30\)boxCluster <- paste0(“Box_”, unique.30$boxID)

all.hits <- merge(all.hits, unique.30, by=“Context”, all.x=TRUE, all.y=TRUE)

#box.div <- all.hits[,c(1:3,12,15,17,38,39,46,49:56)]

Construct FASTA-formatted lines

fasta_lines <- paste0(“>”, unique.30\(boxCluster, "\n", unique.30\)Context) #fasta_lines # Write to file writeLines(fasta_lines, here(“data/inphared_db/14Apr2025_0AUnique.fna”))

clust <- read.csv(here("data/inphared_db/0a_clusters/nested/14Apr2025_0A_nested.csv"), row.names=1)

more idk lol


### nmds angry memory very slow
set.seed(42)
nmds <- metaMDS(cluster_taxa_matrix, distance = "bray", k = 2, trymax = 100)

nmds_points <- as.data.frame(nmds$points)
nmds_points$Cluster <- rownames(nmds_points)

ggplot(nmds_points, aes(x = MDS1, y = MDS2, label = Cluster)) +
  geom_point(size = 3, color = "darkblue") +
  geom_text(vjust = -0.8) +
  labs(title = "NMDS of Flanking Region Clusters by Taxonomy") +
  theme_minimal()



hc <- hclust(bray_dist, method = "average")  # Use "complete", "ward.D", etc. if preferred
plot(hc, main = "Dendrogram of Flanking Clusters by Host Composition",
     xlab = "Cluster", sub = "", hang = -1)


bray_dist <- vegdist(cluster_taxa_matrix, method = "bray")
jaccard_dist <- vegdist(cluster_taxa_matrix, method = "jaccard")

pcoa_result <- cmdscale(jaccard_dist, eig = TRUE, k = 2) # k specifies the number of dimensions to retrieve

pcoa_scores <- as.data.frame(pcoa_result$points)
colnames(pcoa_scores) <- c("PCo1", "PCo2") # Rename columns for clarity
pcoa_eigenvalues <- pcoa_result$eig

pcoa_scores$Group <- metadata$Group

ggplot(pcoa_scores, aes(x = PCo1, y = PCo2, color = Group)) +
  geom_point(size = 3) +
  stat_ellipse() + # Add confidence ellipses for groups (optional)
  labs(title = "PCoA of Jaccard Distances",
       x = paste0("PCo1 (", round(pcoa_eigenvalues[1]/sum(pcoa_eigenvalues) * 100, 2), "%)"),
       y = paste0("PCo2 (", round(pcoa_eigenvalues[2]/sum(pcoa_eigenvalues) * 100, 2), "%)")) +
  theme_bw()



Bd_AS_ob.ord.nmds.bray <- ordinate(, method="NMDS", distance="bray")


Bd_AS_brayplot=plot_ordination(Bd_AS_ob.prop, Bd_AS_ob.ord.nmds.bray, color="BdPos", shape="Type_Site_Year", title="Bray-Curtis Dissimilarity")+ 
  geom_point(size = 3)+ theme_classic()+theme(plot.title=element_text(size=12))

IDK LOL

### chatGPT suggestion
library(DECIPHER)
set.seed(123)
# specify the path to the FASTA file (in quotes)
fas <- here("data/inphared_db/0a_clusters/nested/14Apr2025_0A_80sim.out")

# load the sequences from the file
# change "DNA" to "RNA" or "AA" as needed
seqs <- readDNAStringSet(fas)



cdhit95 <- read.csv("data/inphared_db/0a_clusters/14Apr2025_0A_95_clusters.csv", row.names=1)

dists <- DistanceMatrix(seqs, type = "dist", correction = "Jukes-Cantor")

library(fastcluster)
hc <- hclust(as.dist(dists), method = "average")

## too much memory
## hc <- hclust(as.dist(dists), method = "complete")  # or "average", "ward.D2", etc.

clusters <- Clusterize(seqs,
                       cutoff = 0.1,
                       method = "overlap",
                       includeTerminalGaps = FALSE,
                       minCoverage = 0.5,
                       processors = NULL)  # or NULL for auto

clusters <- cutree(hc, h = 0.1)  # Or set k = number of clusters
# look at some of the sequences (optional)
seqs

clust90 <- Clusterize(seqs,
cutoff=0.1, # >= 90% similar
minCoverage=0.5, # > 50% coverage
processors=NULL) # use all CPUs

clust.90 <- clust90
max(clust.90)
t <- table(clust.90)

mean(t)
tail(sort(t)) # biggest clusters
clust75 <- Clusterize(seqs,
cutoff=0.25, # > 75% similar
minCoverage=0.5, # > 50% coverage
processors=NULL) # use all CPUs

clust.75 <- clust75
max(clust.75)
t <- table(clust.75)

mean(t)
tail(sort(t)) # biggest clusters
clust50 <- Clusterize(seqs,
cutoff=0.5, # > 50% similar
minCoverage=0.5, # > 50% coverage
processors=NULL) # use all CPUs

clust.50 <- clust50
max(clust.50)
t <- table(clust.50)

mean(t)
tail(sort(t)) # biggest clusters

clust.50 <- clust50
clust.90 <- clust90
clust.75 <- clust75

colnames(clust.90) <- c("cluster90")
clust.90$boxCluster <- row.names(clust.90)

colnames(clust.75) <- c("cluster75")
clust.75$boxCluster <- row.names(clust.75)

colnames(clust.50) <- c("cluster50")
clust.50$boxCluster <- row.names(clust.50)
clustnest90.2 <- Clusterize(seqs,
cutoff=seq(0.5, 0.25, -.10)) # use all CPUs

clustnest75 <- Clusterize(seqs,
cutoff=seq(0.5, 0.25, 0)) # use all CPUs

clustnest50 <- Clusterize(seqs,
cutoff=0.5) # use all CPUs




clust.nest <- clustnest90
max(clust.nest$cluster_0_3)
t <- table(clust.75)

mean(t)
tail(sort(t)) # biggest clusters


clustnest.90 <- clustnest90
clustnest.75 <- clustnest75
clustnest.50 <- clustnest50


colnames(clustnest.90) <- c("cluster90")
clustnest.90$boxCluster <- row.names(clustnest.90)

colnames(clustnest.75) <- c("cluster75")
clustnest.75$boxCluster <- row.names(clustnest.75)

colnames(clustnest.50) <- c("cluster50")
clustnest.50$boxCluster <- row.names(clustnest.50)
unique.30.clusts <- merge(unique.30, clustnest.90, by="boxCluster", all.x=TRUE, all.y=TRUE) %>%
  merge(clustnest.75, by="boxCluster", all.x=TRUE, all.y=TRUE) %>%
   merge(clustnest.50, by="boxCluster", all.x=TRUE, all.y=TRUE)

box.div <- merge(all.hits, unique.30.clusts, by="Context", all.x=TRUE, all.y=TRUE)

##note that unique30clusts may NOT be perfectly nested

unique.30.uni <- unique(unique.30.clusts[,c(4:6)])

box.div2 <- select(box.div, phage, Context, Box_Contig, boxID, cluster90, cluster75, cluster50, Host, gtdb_f, f_spor, predicted_label, host_phage_spor, phage_type, sporulation, newgtdb_Phylum, host_phyla, lifestyle)
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQpgYGB7cn0KbGlicmFyeShoZXJlKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShnZ3B1YnIpCmxpYnJhcnkoZXBpdG9vbHMpCmxpYnJhcnkoc2VxaW5yKQpsaWJyYXJ5KGRwbHlyKQpwYWwyIDwtIGMoIiMwMTViNTgiLCAiIzU5NjJiNSIpCnBhbDIuZmxpcCA8LSBjKCIjNTk2MmI1IiwgIiMwMTViNTgiKQpoZXJlOjpoZXJlKCkKCnNvdXJjZShoZXJlKCJ1dGlsaXR5LXNjcmlwdHMvY2QtaGl0LWNsdXN0ZXIuUiIpKQoKYm94IDwtIHJlYWQuZGVsaW0yKGhlcmUoImRhdGEvaW5waGFyZWRfZGIvMTRBcHIyMDI1aW5waF8wQV92My50eHQiICkpCiMjIHJlbW92ZSBleHRyYSAudHh0IGhlYWRlcnMgZnJvbSBjYXR0aW5nIGZpbGVzCmJveCA8LSBzdWJzZXQoYm94LCBib3gkQ29udGV4dCE9IkNvbnRleHQiKQojIyMgcmVtb3ZlIGluY29tcGxldGUgZmxhbmtpbmcgcmVnaW9ucwpib3ggPC0gc3Vic2V0KGJveCwgYm94JFBhcnRpYWw9PSJOb25lIikKCmJveCA8LSBib3ggJT4lIHJlbmFtZShwcm9kdWN0ID0gU2VxdWVuY2UsIHBoYWdlID0gQ29udGlnKQpib3hbLGMoMildIDwtICIwQSIKI2JveCA8LSBib3hbLGMoMywyLDEpXQpib3gkY291bnQgPC0gMQoKCiMjIEZKMjMwOTYwIHNwbzEKIyMgRVU3NzEwOTIgcGhpMjkKIyMgRVU2MjI4MDggbmYKIyMgS1kwMzA3ODIgcGhpM3QKIyMgQUYwMjA3MTMKCgpgYGAKCiMjIGlmIGkgbmVlZGVkIHRvIGRvIHJldmVyc2UgY29tcGxlbWVudCwgZG9uJ3QgcmlnaHQgbm93CmJveCRSZXZDb21wIDwtIHNhcHBseShib3gkQ29udGV4dCwgZnVuY3Rpb24ocykgewogIGMycyhyZXYoY29tcChzMmMocyksIGZvcmNlVG9Mb3dlciA9IEZBTFNFKSkpCn0pCgoKYm94JEZpdmUyVGhyZWUgPC0gaWZlbHNlKGJveCRTdHJhbmQ9PSIrIiwgYm94JENvbnRleHQsIGJveCRSZXZDb21wKSAKCgpgYGB7cn0KYm94LmFsbCA8LSBib3gKCnBoYWdlIDwtIHJlYWQuY3N2KGhlcmUoImRhdGEvaW5waGFyZWRfZGIvMTRBcHIyMDI1X2tub3duc3BvcmVzdGF0dXMuY3N2IiksIHJvdy5uYW1lcz0xKQoKCgoKYWxsIDwtIG1lcmdlKGJveCwgcGhhZ2UsIGJ5Lng9InBoYWdlIiwgYnkueT0iQWNjZXNzaW9uIiwgYWxsLng9RkFMU0UsIGFsbC55PVRSVUUpIAoKYWxsJHByb2R1Y3RbaXMubmEoYWxsJHByb2R1Y3QpXSA8LSAiTm9fMEEiCgphbGwuaGl0cyA8LSBzdWJzZXQoYWxsLCBhbGwkcHJvZHVjdD09IjBBIikKCgphbGwuaGl0cyRzdHJhbmQyIDwtIGlmZWxzZShhbGwuaGl0cyRTdHJhbmQ9PSIrIiwgIkZ3ZCIsICJSZXYiKQoKYWxsLmhpdHMgPC0gdW5pdGUoYWxsLmhpdHMsICJCb3hfQ29udGlnIiwgYygicGhhZ2UiLCAicHJvZHVjdCIsICJzdHJhbmQyIiwgIlBvc2l0aW9uIiksIHNlcCA9ICJfIiwgcmVtb3ZlID0gRkFMU0UsIG5hLnJtID0gRkFMU0UpCgoKYWxsLmhpdHNbXSA8LSBsYXBwbHkoYWxsLmhpdHMsIGZ1bmN0aW9uKHgpIHsKICBpZiAoaXMuY2hhcmFjdGVyKHgpKSB7CiAgICBnc3ViKCJEZXN1bGZvYmFjdGVyb3RhX0kiLCAiRGVzdWxmb2JhY3Rlcm90YSIsIHgpCiAgfSBlbHNlIHsKICAgIHgKICB9Cn0pCgphbGwuaGl0c1tdIDwtIGxhcHBseShhbGwuaGl0cywgZnVuY3Rpb24oeCkgewogIGlmIChpcy5jaGFyYWN0ZXIoeCkpIHsKICAgIGdzdWIoIkJhY3Rlcm9pZG90YV9BIiwgIkJhY3Rlcm9pZG90YSIsIHgpCiAgfSBlbHNlIHsKICAgIHgKICB9Cn0pCgphbGwuaGl0c1tdIDwtIGxhcHBseShhbGwuaGl0cywgZnVuY3Rpb24oeCkgewogIGlmIChpcy5jaGFyYWN0ZXIoeCkpIHsKICAgIGdzdWIoIkJhY2lsbGFjZWFlX0MiLCAiQmFjaWxsYWNlYWUiLCB4KQogIH0gZWxzZSB7CiAgICB4CiAgfQp9KQoKYWxsLmhpdHNbXSA8LSBsYXBwbHkoYWxsLmhpdHMsIGZ1bmN0aW9uKHgpIHsKICBpZiAoaXMuY2hhcmFjdGVyKHgpKSB7CiAgICBnc3ViKCJCYWNpbGxhY2VhZV9DIiwgIkJhY2lsbGFjZWFlIiwgeCkKICB9IGVsc2UgewogICAgeAogIH0KfSkKCmFsbC5oaXRzW10gPC0gbGFwcGx5KGFsbC5oaXRzLCBmdW5jdGlvbih4KSB7CiAgaWYgKGlzLmNoYXJhY3Rlcih4KSkgewogICAgZ3N1YigiQmFjaWxsYWxlc19EIiwgIkJhY2lsbGFsZXMiLCB4KQogIH0gZWxzZSB7CiAgICB4CiAgfQp9KQoKYWxsLmhpdHNbXSA8LSBsYXBwbHkoYWxsLmhpdHMsIGZ1bmN0aW9uKHgpIHsKICBpZiAoaXMuY2hhcmFjdGVyKHgpKSB7CiAgICBnc3ViKCJCYWNpbGxhbGVzX0EiLCAiQmFjaWxsYWxlcyIsIHgpCiAgfSBlbHNlIHsKICAgIHgKICB9Cn0pCgphbGwuaGl0c1tdIDwtIGxhcHBseShhbGwuaGl0cywgZnVuY3Rpb24oeCkgewogIGlmIChpcy5jaGFyYWN0ZXIoeCkpIHsKICAgIGdzdWIoIkJhY2lsbGFsZXNfQiIsICJCYWNpbGxhbGVzIiwgeCkKICB9IGVsc2UgewogICAgeAogIH0KfSkKCgpgYGAKCgpgYGB7cn0KCgoKIyBDb25zdHJ1Y3QgRkFTVEEtZm9ybWF0dGVkIGxpbmVzCmZhc3RhX2xpbmVzIDwtIHBhc3RlMCgiPiIsIGFsbC5oaXRzJEJveF9Db250aWcsICJcbiIsIGFsbC5oaXRzJENvbnRleHRfbm9fbW90aWYpCiNmYXN0YV9saW5lcwojIFdyaXRlIHRvIGZpbGUKd3JpdGVMaW5lcyhmYXN0YV9saW5lcywgaGVyZSgiZGF0YS9pbnBoYXJlZF9kYi8xNEFwcjIwMjVfMEFoaXRzX25vcGFydGlhbHMuZm5hIikpCiAgICAgICAgICAgCiAgICAgICAgICAgCiAgICAgICAgICAgCmBgYAoKCgpgYGB7cn0KY2x1c3QgPC0gcmVhZC5jc3YoaGVyZSgiZGF0YS9pbnBoYXJlZF9kYi8wYV9jbHVzdGVycy9uZXN0ZWQvMTRBcHIyMDI1XzBBX25lc3RlZC5jc3YiKSwgcm93Lm5hbWVzPTEpCgpgYGAKCgpgYGB7cn0KCmxpYnJhcnkoREVDSVBIRVIpCnNldC5zZWVkKDEyMykKIyBzcGVjaWZ5IHRoZSBwYXRoIHRvIHRoZSBGQVNUQSBmaWxlIChpbiBxdW90ZXMpCmZhcyA8LSBoZXJlKCJkYXRhL2lucGhhcmVkX2RiLzBhX2NsdXN0ZXJzL25lc3RlZC8xNEFwcjIwMjVfMEFfODBzaW0ub3V0IikKCiMgbG9hZCB0aGUgc2VxdWVuY2VzIGZyb20gdGhlIGZpbGUKIyBjaGFuZ2UgIkROQSIgdG8gIlJOQSIgb3IgIkFBIiBhcyBuZWVkZWQKbiAKCgoKY2x1c3QuNTAgPC0gQ2x1c3Rlcml6ZShzZXFzLApjdXRvZmY9MC41LCAjID4gNTAlIHNpbWlsYXIKbWluQ292ZXJhZ2U9MC41LCAjID4gNTAlIGNvdmVyYWdlCnByb2Nlc3NvcnM9TlVMTCkgIyB1c2UgYWxsIENQVXMKCmNsdXN0NTAgPC0gY2x1c3QuNTAKY2x1c3Q1MCRTZXF1ZW5jZV9JRCA8LSByb3cubmFtZXMoY2x1c3Q1MCkKY2x1c3Q1MCRjbHVzdGVyPC0gcGFzdGUwKCI1MF8iLCBjbHVzdDUwJGNsdXN0ZXIpCgpjbHVzdC5zdXBlciA8LSBtZXJnZShjbHVzdCwgY2x1c3Q1MCwgYnk9IlNlcXVlbmNlX0lEIiwgYWxsPVRSVUUpCmNsdXN0ODA1MCA8LSB1bmlxdWUoY2x1c3Quc3VwZXJbLGMoNjo3KV0pCmNsdXN0ODA1MCA8LSBuYS5vbWl0KGNsdXN0ODA1MCkKY29sbmFtZXMoY2x1c3Q4MDUwKSA8LSBjKCJDbHVzdGVyODAiLCAiQ2x1c3RlcjUwIikKCgpjbHVzdCA8LSBtZXJnZShjbHVzdCwgY2x1c3Q4MDUwLCBieT0iQ2x1c3RlcjgwIiwgYWxsPVRSVUUpCgoKYGBgCgoKYGBge3J9CgphbGwuY2x1c3QgPC0gbWVyZ2UoYWxsLmhpdHMsIGNsdXN0LCBieS54PSJCb3hfQ29udGlnIiwgYnkueT0iU2VxdWVuY2VfSUQiLCBhbGwueD1UUlVFLCBhbGwueT1UUlVFKQoKCmdjX2NvbnRlbnQgPC0gZnVuY3Rpb24oc2VxKSB7CiAgc2VxIDwtIHRvdXBwZXIoc2VxKQogIGJhc2VzIDwtIHN0cnNwbGl0KHNlcSwgIiIpW1sxXV0KICBnY19jb3VudCA8LSBzdW0oYmFzZXMgJWluJSBjKCJHIiwgIkMiKSkKICB0b3RhbCA8LSBsZW5ndGgoYmFzZXMpCiAgcmV0dXJuKGdjX2NvdW50IC8gdG90YWwpCn0KCiMgVmVjdG9yaXplZCB2ZXJzaW9uIGZvciBtdWx0aXBsZSBzZXF1ZW5jZXMKZ2NfY29udGVudF92ZWMgPC0gZnVuY3Rpb24oc2VxcykgewogIHNhcHBseShzZXFzLCBnY19jb250ZW50KQp9CgoKYWxsLmNsdXN0JEdDLmZsYW5rcyA8LSBnY19jb250ZW50X3ZlYyhhbGwuY2x1c3QkVXBzdHJlYW0pCgoKZ2MuY2hlY2sgPC0gc2VsZWN0KGFsbC5jbHVzdCwgQm94X0NvbnRpZywgcGhhZ2UsIEdDLmZsYW5rcywgQ29udGV4dCwgQ29udGV4dF9ub19tb3RpZiwgZ3RkYl9mLCBmX3Nwb3IsIHByZWRpY3RlZF9sYWJlbCwgaG9zdF9waGFnZV9zcG9yLCBwaGFnZV90eXBlLCBzcG9ydWxhdGlvbiwgbmV3Z3RkYl9QaHlsdW0sIGhvc3RfcGh5bGEsIGxpZmVzdHlsZSwpCgoKCmdjLmNoZWNrLm1lYW4ubm9maWx0IDwtIGdjLmNoZWNrICU+JQogIGdyb3VwX2J5KGhvc3RfcGhhZ2Vfc3BvcikgJT4lCiAgc3VtbWFyaXNlKGdjX21lYW4gPSBtZWFuKEdDLmZsYW5rcyksIHRvdGFsPW4oKSkKCiNnYy5jaGVjayA8LSBzdWJzZXQoZ2MuY2hlY2ssIGdjLmNoZWNrJEdDLmZsYW5rczwwLjM1KQoKZ2MuY2hlY2subWVhbiA8LSBnYy5jaGVjayAlPiUKICBncm91cF9ieShob3N0X3BoYWdlX3Nwb3IpICU+JQogIHN1bW1hcmlzZShnY19tZWFuID0gbWVhbihHQy5mbGFua3MpLCB0b3RhbD1uKCkpCgoKYWxsLmNsdXN0LmNsZWFuIDwtIGFsbC5jbHVzdApgYGAKCgpgYGB7cn0KCmFsbC5jbHVzdCA8LSBzdWJzZXQoYWxsLmNsdXN0LmNsZWFuLCBhbGwuY2x1c3QuY2xlYW4kR0MuZmxhbmtzPDAuMzUpCmhvc3QuY2x1c3QgPC0gYWxsLmNsdXN0ICU+JQogIGdyb3VwX2J5KENsdXN0ZXI1MCwgSG9zdCkgJT4lCiAgc3VtbWFyaXNlKG4gPSBuKCkpICU+JQogIGFycmFuZ2UoZGVzYyhuKSkKCgoKCgpjbHVzdGVyX3N1cGVyLm1hdHJpeCA8LSBhbGwuY2x1c3QgJT4lCiAgZ3JvdXBfYnkoQ2x1c3RlcjUwLCBob3N0c3BlY19waGFnZV9zcG9yKSAlPiUKICBzdW1tYXJpc2UoY291bnQgPSBuKCksIC5ncm91cHMgPSAiZHJvcCIpICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBob3N0c3BlY19waGFnZV9zcG9yLCB2YWx1ZXNfZnJvbSA9IGNvdW50LCB2YWx1ZXNfZmlsbCA9IDApICU+JQogIGNvbHVtbl90b19yb3duYW1lcygiQ2x1c3RlcjUwIikgJT4lCiAgYXMubWF0cml4KCkKCnQuc3VwZXIgPC0gdChjbHVzdGVyX3N1cGVyLm1hdHJpeCkKCmNsdXN0ZXJfdGF4YV9tYXRyaXggPC0gYWxsLmNsdXN0ICU+JQogIGdyb3VwX2J5KENsdXN0ZXI1MCwgaG9zdF9waGFnZV9zcG9yKSAlPiUKICBzdW1tYXJpc2UoY291bnQgPSBuKCksIC5ncm91cHMgPSAiZHJvcCIpICU+JQogIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSBob3N0X3BoYWdlX3Nwb3IsIHZhbHVlc19mcm9tID0gY291bnQsIHZhbHVlc19maWxsID0gMCkgJT4lCiAgY29sdW1uX3RvX3Jvd25hbWVzKCJDbHVzdGVyNTAiKSAlPiUKICBhcy5tYXRyaXgoKQoKdC5hbGwgPC0gdChjbHVzdGVyX3RheGFfbWF0cml4KQoKI2FsbC5jbHVzdC5iYWNpbGwgPC0gc3Vic2V0KGFsbC5jbHVzdCwgYWxsLmNsdXN0JG5ld2d0ZGJfUGh5bHVtPT0iQmFjaWxsb3RhIiB8IGFsbC5jbHVzdCRuZXdndGRiX1BoeWx1bT09IlBzZXVkb21vbmFkb3RhIikKCmFsbC5jbHVzdC5iYWNpbGwgPC0gc3Vic2V0KGFsbC5jbHVzdCwgYWxsLmNsdXN0JG5ld2d0ZGJfUGh5bHVtPT0iQmFjaWxsb3RhIikKCmNsdXN0ZXJfdGF4YV9tYXRyaXggPC0gYWxsLmNsdXN0LmJhY2lsbCAlPiUKICBncm91cF9ieShDbHVzdGVyNTAsIHBoYWdlX3R5cGUpICU+JQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHBoYWdlX3R5cGUsIHZhbHVlc19mcm9tID0gY291bnQsIHZhbHVlc19maWxsID0gMCkgJT4lCiAgY29sdW1uX3RvX3Jvd25hbWVzKCJDbHVzdGVyNTAiKSAlPiUKICBhcy5tYXRyaXgoKQoKdC5iYWNpbGxpIDwtIHQoY2x1c3Rlcl90YXhhX21hdHJpeCkKCgpjbHVzdGVyX3RheGFfbWF0cml4IDwtIGFsbC5jbHVzdC5iYWNpbGwgJT4lCiAgZ3JvdXBfYnkoQ2x1c3RlcjUwLCBwaGFnZSkgJT4lCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gcGhhZ2UsIHZhbHVlc19mcm9tID0gY291bnQsIHZhbHVlc19maWxsID0gMCkgJT4lCiAgY29sdW1uX3RvX3Jvd25hbWVzKCJDbHVzdGVyNTAiKSAlPiUKICBhcy5tYXRyaXgoKQoKYWxsLmNsdXN0LmJhY2lsbCA8LSB1bml0ZShhbGwuY2x1c3QuYmFjaWxsLCAiZmFtX2xpZmUiLCBjKCJndGRiX2YiLCAibGlmZXN0eWxlIiksIHNlcCA9ICJfIiwgcmVtb3ZlID0gRkFMU0UsIG5hLnJtID0gRkFMU0UpCgoKY2x1c3Rlcl9mYW1fbWF0cml4IDwtIGFsbC5jbHVzdC5iYWNpbGwgJT4lCiAgZ3JvdXBfYnkoQ2x1c3RlcjUwLCBmYW1fbGlmZSkgJT4lCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpLCAuZ3JvdXBzID0gImRyb3AiKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gZmFtX2xpZmUsIHZhbHVlc19mcm9tID0gY291bnQsIHZhbHVlc19maWxsID0gMCkgJT4lCiAgY29sdW1uX3RvX3Jvd25hbWVzKCJDbHVzdGVyNTAiKSAlPiUKICBhcy5tYXRyaXgoKQoKdC5iYWNpbGxpLmZhbSA8LSB0KGNsdXN0ZXJfZmFtX21hdHJpeCkKCmxpYnJhcnkocGhlYXRtYXApCgpwaGVhdG1hcCh0LmFsbCwKICAgICAgICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwKICAgICAgICAgY2x1c3Rlcl9jb2xzID0gVFJVRSwKICAgICAgICAgZGlzcGxheV9udW1iZXJzID0gVFJVRSwKICAgICAgICAgZm9udHNpemUgPSAxMCwKICAgICAgICAgbWFpbiA9ICJUYXhvbm9taWMgQ29tcG9zaXRpb24gYnkgRmxhbmtpbmcgU2VxdWVuY2UgQ2x1c3RlciIpCgoKcGhlYXRtYXAodC5iYWNpbGxpLAogICAgICAgICBjbHVzdGVyX3Jvd3MgPSBUUlVFLAogICAgICAgICBjbHVzdGVyX2NvbHMgPSBUUlVFLAogICAgICAgICBkaXNwbGF5X251bWJlcnMgPSBUUlVFLAogICAgICAgICBmb250c2l6ZSA9IDEwLAogICAgICAgICBtYWluID0gIlRheG9ub21pYyBDb21wb3NpdGlvbiBieSBGbGFua2luZyBTZXF1ZW5jZSBDbHVzdGVyIikKCnBoZWF0bWFwKHQuYmFjaWxsaS5mYW0sCiAgICAgICAgIGNsdXN0ZXJfcm93cyA9IFRSVUUsCiAgICAgICAgIGNsdXN0ZXJfY29scyA9IFRSVUUsCiAgICAgICAgIGRpc3BsYXlfbnVtYmVycyA9IFRSVUUsCiAgICAgICAgIGZvbnRzaXplID0gMTAsCiAgICAgICAgIG1haW4gPSAiVGF4b25vbWljIENvbXBvc2l0aW9uIGJ5IEZsYW5raW5nIFNlcXVlbmNlIENsdXN0ZXIiKQoKCgpsaWJyYXJ5KHZlZ2FuKQpsaWJyYXJ5KGdncGxvdDIpCgoKCgpicmF5X2Rpc3QuYmFjIDwtIHZlZ2Rpc3QodC5iYWNpbGxpLCBtZXRob2QgPSAiYnJheSIpCmphY2NhcmRfZGlzdC5iYWMgPC0gdmVnZGlzdCh0LmJhY2lsbGksIG1ldGhvZCA9ICJqYWNjYXJkIikKCgoKaGMuamFjLmJhYyA8LSBoY2x1c3QoamFjY2FyZF9kaXN0LmJhYywgbWV0aG9kID0gIndhcmQuRCIpICAjIFVzZSAiY29tcGxldGUiLCAid2FyZC5EIiwgZXRjLiBpZiBwcmVmZXJyZWQKcGxvdChoYy5qYWMuYmFjLCBtYWluID0gIldhcmQuRCBDbHVzdGVyaW5nIG9mIDBBIEZsYW5rcyBpbiBQaGFnZXMgYnkgSG9zdCIsCiAgICAgeGxhYiA9ICJDbHVzdGVyIiwgc3ViID0gIiIsIGhhbmcgPSAtMSkKCgpoYy5icmF5LmJhYyA8LSBoY2x1c3QoYnJheV9kaXN0LmJhYywgbWV0aG9kID0gIndhcmQuRCIpICAjIFVzZSAiY29tcGxldGUiLCAid2FyZC5EIiwgZXRjLiBpZiBwcmVmZXJyZWQKcGxvdChoYy5icmF5LmJhYywgbWFpbiA9ICJEZW5kcm9ncmFtIG9mIEZsYW5raW5nIENsdXN0ZXJzIGJ5IEhvc3QgQ29tcG9zaXRpb24iLAogICAgIHhsYWIgPSAiQ2x1c3RlciIsIHN1YiA9ICIiLCBoYW5nID0gLTEpCgoKCgpicmF5X2Rpc3QuYWxsIDwtIHZlZ2Rpc3QodC5hbGwsIG1ldGhvZCA9ICJicmF5IikKamFjY2FyZF9kaXN0LmFsbCA8LSB2ZWdkaXN0KHQuYWxsLCBtZXRob2QgPSAiamFjY2FyZCIpCgoKaGMuYnJheS5hbGwgPC0gaGNsdXN0KGJyYXlfZGlzdC5hbGwsIG1ldGhvZCA9ICJ3YXJkLkQiKSAgIyBVc2UgImNvbXBsZXRlIiwgIndhcmQuRCIsIGV0Yy4gaWYgcHJlZmVycmVkCnBsb3QoaGMuYnJheS5hbGwsIG1haW4gPSAiRGVuZHJvZ3JhbSBvZiBGbGFua2luZyBDbHVzdGVycyBieSBIb3N0IENvbXBvc2l0aW9uIiwKICAgICB4bGFiID0gIkNsdXN0ZXIiLCBzdWIgPSAiIiwgaGFuZyA9IC0xKQoKaGMuZGlzdC5hbGwgPC0gaGNsdXN0KGphY2NhcmRfZGlzdC5hbGwsIG1ldGhvZCA9ICJ3YXJkLkQiKSAgIyBVc2UgImNvbXBsZXRlIiwgIndhcmQuRCIsIGV0Yy4gaWYgcHJlZmVycmVkCnBhcihtYXIgPSBjKDUsIDgsIDQsIDE1KSkgICMgYWRqdXN0IGFzIG5lZWRlZApwbG90KGFzLmRlbmRyb2dyYW0oaGMuZGlzdC5hbGwpLAogICAgIG1haW4gPSAiV2FyZC5EIENsdXN0ZXJpbmcgb2YgMEEgRmxhbmtzIGluIFBoYWdlcyBieSBIb3N0IiwKICAgICB4bGFiID0gIkhlaWdodCIsIHlsYWIgPSAiQ2x1c3RlciIsCiAgICAgc3ViID0gIiIsIGhvcml6ID0gVFJVRSkKCgpnZ3NhdmUoaGVyZSgibGFiX3ByZXMvV2FyZF9CYWNWc090aGVyMEFfamFjYy5wbmciKSkKYGBgCgoKYGBge3J9CmJyYXlfZGlzdC5waHkgPC0gdmVnZGlzdCh0LnN1cGVyLCBtZXRob2QgPSAiYnJheSIpCmphY2NhcmRfZGlzdC5waHkgPC0gdmVnZGlzdCh0LnN1cGVyLCBtZXRob2QgPSAiamFjY2FyZCIpCgpoYy5icmF5LnBoeSA8LSBoY2x1c3QoYnJheV9kaXN0LnBoeSwgbWV0aG9kID0gIndhcmQuRCIpICAjIFVzZSAiY29tcGxldGUiLCAid2FyZC5EIiwgZXRjLiBpZiBwcmVmZXJyZWQKcGxvdChoYy5icmF5LnBoeSwgbWFpbiA9ICJEZW5kcm9ncmFtIG9mIEZsYW5raW5nIENsdXN0ZXJzIGJ5IEhvc3QgQ29tcG9zaXRpb24iLAogICAgIHhsYWIgPSAiQ2x1c3RlciIsIHN1YiA9ICIiLCBoYW5nID0gLTEpCgpoYy5kaXN0LnBoeSA8LSBoY2x1c3QoamFjY2FyZF9kaXN0LnBoeSwgbWV0aG9kID0gIndhcmQuRCIpICAjIFVzZSAiY29tcGxldGUiLCAid2FyZC5EIiwgZXRjLiBpZiBwcmVmZXJyZWQKcGxvdChoYy5kaXN0LnBoeSwgbWFpbiA9ICJXYXJkLkQgQ2x1c3RlcmluZyBvZiAwQSBGbGFua3MgaW4gUGhhZ2VzIGJ5IEhvc3QiLAogICAgIHhsYWIgPSAiQ2x1c3RlciIsIHN1YiA9ICIiLCBoYW5nID0gLTEpCgoKZ2dzYXZlKGhlcmUoImxhYl9wcmVzL1dhcmRfUGh5MEFfamFjYy5wbmciKSkKCgpqYWNjYXJkX2Rpc3QuZmFtIDwtIHZlZ2Rpc3QodC5iYWNpbGxpLmZhbSwgbWV0aG9kID0gImphY2NhcmQiKQpoYy5kaXN0LnBoeSA8LSBoY2x1c3QoamFjY2FyZF9kaXN0LmZhbSwgbWV0aG9kID0gIndhcmQuRCIpICAjIFVzZSAiY29tcGxldGUiLCAid2FyZC5EIiwgZXRjLiBpZiBwcmVmZXJyZWQKcGFyKG1hciA9IGMoNSwgOCwgNCwgMTUpKSAgIyBhZGp1c3QgYXMgbmVlZGVkCgojIFRoZW4gcGxvdCB5b3VyIGRlbmRyb2dyYW0KcGxvdChhcy5kZW5kcm9ncmFtKGhjLmRpc3QucGh5KSwKICAgICBtYWluID0gIldhcmQuRCBDbHVzdGVyaW5nIG9mIDBBIEZsYW5rcyBpbiBQaGFnZXMgYnkgSG9zdCIsCiAgICAgeGxhYiA9ICJIZWlnaHQiLCB5bGFiID0gIkNsdXN0ZXIiLAogICAgIHN1YiA9ICIiLCBob3JpeiA9IFRSVUUpCmBgYAoKYGBge3J9CmxpYnJhcnkoZGVuZGV4dGVuZCkKCgpqYWNjYXJkX2Rpc3QuZmFtIDwtIHZlZ2Rpc3QodC5iYWNpbGxpLmZhbSwgbWV0aG9kID0gImphY2NhcmQiKQpoYy5kaXN0LnBoeSA8LSBoY2x1c3QoamFjY2FyZF9kaXN0LmZhbSwgbWV0aG9kID0gIndhcmQuRCIpICAjIFVzZSAiY29tcGxldGUiLCAid2FyZC5EIiwgZXRjLiBpZiBwcmVmZXJyZWQKcGFyKG1hciA9IGMoNSwgOCwgNCwgMTUpKSAgIyBhZGp1c3QgYXMgbmVlZGVkCgojIFRoZW4gcGxvdCB5b3VyIGRlbmRyb2dyYW0KcGxvdChhcy5kZW5kcm9ncmFtKGhjLmRpc3QucGh5KSwKICAgICBtYWluID0gIldhcmQuRCBDbHVzdGVyaW5nIG9mIDBBIEZsYW5rcyBpbiBQaGFnZXMgYnkgSG9zdCIsCiAgICAgeGxhYiA9ICJIZWlnaHQiLCB5bGFiID0gIkNsdXN0ZXIiLAogICAgIHN1YiA9ICIiLCBob3JpeiA9IFRSVUUpCgoKIyAyLiBDb252ZXJ0IHRvIGRlbmRyb2dyYW0gb2JqZWN0CmRlbmQgPC0gYXMuZGVuZHJvZ3JhbShoYy5kaXN0LnBoeSkKCgoKbWV0YSA8LSBzZWxlY3QoYWxsLmNsdXN0LmJhY2lsbCwgaG9zdHNwZWNfcGhhZ2Vfc3Bvciwgc3BvcnVsYXRpb24sIGxpZmVzdHlsZSwgaG9zdF9waHlsYSxuZXdndGRiX1BoeWx1bSwgZmFtX2xpZmUsIGd0ZGJfZikKbWV0YSA8LSB1bmlxdWUobWV0YSkKcm93bmFtZXMobWV0YSkgPC0gbWV0YSRmYW1fbGlmZQoKIyBFbnN1cmUgcm93bmFtZXMgb2YgbWV0YSBhcmUgZmFtX2xpZmUsIHdoaWNoIG1hdGNoIGRlbmQgbGFiZWxzCnJvd25hbWVzKG1ldGEpIDwtIG1ldGEkZmFtX2xpZmUKZ3JvdXBfdmVjdG9yIDwtIG1ldGEkZ3RkYl9mCm5hbWVzKGdyb3VwX3ZlY3RvcikgPC0gbWV0YSRmYW1fbGlmZQpsYWJlbF9vcmRlciA8LSBsYWJlbHMoZGVuZCkKZ3JvdXBfdmVjdG9yIDwtIGdyb3VwX3ZlY3RvcltsYWJlbF9vcmRlcl0KCmxpYnJhcnkoZGVuZGV4dGVuZCkKCgpsaWJyYXJ5KHZpcmlkaXMpCnBhbGV0dGUgPC0gdHVyYm8obGVuZ3RoKHVuaXF1ZShncm91cF92ZWN0b3IpKSkKCiMgU2FtZSBhcyBhYm92ZQp0aXBfY29sb3JzIDwtIHNldE5hbWVzKHBhbGV0dGUsIGxldmVscyhhcy5mYWN0b3IoZ3JvdXBfdmVjdG9yKSkpW2dyb3VwX3ZlY3Rvcl0KCmRlbmRfY29sb3JlZCA8LSBkZW5kICU+JQogIHNldCgibGFiZWxzX2NvbG9ycyIsIHZhbHVlID0gdGlwX2NvbG9ycykKCnBhcihtYXIgPSBjKDUsIDgsIDQsIDE1KSkKcGxvdChkZW5kX2NvbG9yZWQsIG1haW4gPSAiQ2x1c3RlcmVkIGJ5IGZhbV9saWZlLCBDb2xvcmVkIGJ5IEdUREIgRmFtaWx5IiwgaG9yaXogPSBUUlVFKQoKbGVnZW5kKCJ0b3ByaWdodCIsIGxlZ2VuZCA9IHVuaXF1ZShncm91cF92ZWN0b3IpLAogICAgICAgZmlsbCA9IGFzLm51bWVyaWMoYXMuZmFjdG9yKHVuaXF1ZShncm91cF92ZWN0b3IpKSksIGJvcmRlciA9IE5BLCBidHkgPSAibiIpCgoKCiMgNC4gQ29sb3IgdGhlIGJyYW5jaGVzIG9yIGxhYmVscwpkZW5kX2NvbG9yZWQgPC0gZGVuZCAlPiUKICBzZXQoImxhYmVsc19jb2xvcnMiLCB2YWx1ZSA9IGFzLm51bWVyaWMoYXMuZmFjdG9yKGdyb3VwX3ZlY3RvcikpKSMgJT4lCiAgI3NldCgiYnJhbmNoZXNfa19jb2xvciIsIGsgPSBsZW5ndGgodW5pcXVlKGdyb3VwX3ZlY3RvcikpKSAgIyBvcHRpb25hbAoKCnBhcihtYXIgPSBjKDUsIDgsIDQsIDE1KSkgICMgYWRqdXN0IGFzIG5lZWRlZApwbG90KGFzLmRlbmRyb2dyYW0oZGVuZF9jb2xvcmVkKSwKICAgICBtYWluID0gIldhcmQuRCBDbHVzdGVyaW5nIG9mIDBBIEZsYW5rcyBpbiBQaGFnZXMgYnkgSG9zdCIsCiAgICAgeGxhYiA9ICJIZWlnaHQiLCB5bGFiID0gIkNsdXN0ZXIiLAogICAgIHN1YiA9ICIiLCBob3JpeiA9IFRSVUUpCgpgYGAKCgpgYGB7cn0KbGlicmFyeShkZW5kZXh0ZW5kKQphbGwuY2x1c3QuYmFjaWxsIDwtIHN1YnNldChhbGwuY2x1c3QsIGFsbC5jbHVzdCRuZXdndGRiX1BoeWx1bT09IkJhY2lsbG90YSIpCmFsbC5jbHVzdC5iYWNpbGwgPC0gdW5pdGUoYWxsLmNsdXN0LmJhY2lsbCwgIm9yZF9saWZlIiwgYygibmV3Z3RkYl9PcmRlciIsICJsaWZlc3R5bGUiLCAic3BvcnVsYXRpb24iKSwgc2VwID0gIl8iLCByZW1vdmUgPSBGQUxTRSwgbmEucm0gPSBGQUxTRSkKCgpjbHVzdGVyX29yZGVyX21hdHJpeCA8LSBhbGwuY2x1c3QuYmFjaWxsICU+JQogIGdyb3VwX2J5KENsdXN0ZXI1MCwgb3JkX2xpZmUpICU+JQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IG9yZF9saWZlLCB2YWx1ZXNfZnJvbSA9IGNvdW50LCB2YWx1ZXNfZmlsbCA9IDApICU+JQogIGNvbHVtbl90b19yb3duYW1lcygiQ2x1c3RlcjUwIikgJT4lCiAgYXMubWF0cml4KCkKCnQuYmFjaWxsaS5vcmQgPC0gdChjbHVzdGVyX29yZGVyX21hdHJpeCkKCgoKamFjY2FyZF9kaXN0Lm9yZCA8LSB2ZWdkaXN0KHQuYmFjaWxsaS5vcmQsIG1ldGhvZCA9ICJqYWNjYXJkIikKaGMuZGlzdC5waHkgPC0gaGNsdXN0KGphY2NhcmRfZGlzdC5vcmQsIG1ldGhvZCA9ICJ3YXJkLkQiKSAgIyBVc2UgImNvbXBsZXRlIiwgIndhcmQuRCIsIGV0Yy4gaWYgcHJlZmVycmVkCnBhcihtYXIgPSBjKDUsIDgsIDQsIDE1KSkgICMgYWRqdXN0IGFzIG5lZWRlZAoKIyBUaGVuIHBsb3QgeW91ciBkZW5kcm9ncmFtCnBsb3QoYXMuZGVuZHJvZ3JhbShoYy5kaXN0LnBoeSksCiAgICAgbWFpbiA9ICJXYXJkLkQgQ2x1c3RlcmluZyBvZiAwQSBGbGFua3MgaW4gUGhhZ2VzIGJ5IEhvc3QiLAogICAgIHhsYWIgPSAiSGVpZ2h0IiwgeWxhYiA9ICJDbHVzdGVyIiwKICAgICBzdWIgPSAiIiwgaG9yaXogPSBUUlVFKQoKCiMgMi4gQ29udmVydCB0byBkZW5kcm9ncmFtIG9iamVjdApkZW5kIDwtIGFzLmRlbmRyb2dyYW0oaGMuZGlzdC5waHkpCgoKCm1ldGEgPC0gc2VsZWN0KGFsbC5jbHVzdC5iYWNpbGwsIGhvc3RzcGVjX3BoYWdlX3Nwb3IsIHNwb3J1bGF0aW9uLCBsaWZlc3R5bGUsIGhvc3RfcGh5bGEsbmV3Z3RkYl9QaHlsdW0sIG9yZF9saWZlLCBuZXdndGRiX09yZGVyKQptZXRhIDwtIHVuaXF1ZShtZXRhKQpyb3duYW1lcyhtZXRhKSA8LSBtZXRhJG9yZF9saWZlCgojIEVuc3VyZSByb3duYW1lcyBvZiBtZXRhIGFyZSBmYW1fbGlmZSwgd2hpY2ggbWF0Y2ggZGVuZCBsYWJlbHMKcm93bmFtZXMobWV0YSkgPC0gbWV0YSRvcmRfbGlmZQpncm91cF92ZWN0b3IgPC0gbWV0YSRuZXdndGRiX09yZGVyCm5hbWVzKGdyb3VwX3ZlY3RvcikgPC0gbWV0YSRvcmRfbGlmZQpsYWJlbF9vcmRlciA8LSBsYWJlbHMoZGVuZCkKZ3JvdXBfdmVjdG9yIDwtIGdyb3VwX3ZlY3RvcltsYWJlbF9vcmRlcl0KCmxpYnJhcnkoZGVuZGV4dGVuZCkKCgpsaWJyYXJ5KHZpcmlkaXMpCnBhbGV0dGUgPC0gdHVyYm8obGVuZ3RoKHVuaXF1ZShncm91cF92ZWN0b3IpKSkKCiMgU2FtZSBhcyBhYm92ZQp0aXBfY29sb3JzIDwtIHNldE5hbWVzKHBhbGV0dGUsIGxldmVscyhhcy5mYWN0b3IoZ3JvdXBfdmVjdG9yKSkpW2dyb3VwX3ZlY3Rvcl0KCmRlbmRfY29sb3JlZCA8LSBkZW5kICU+JQogIHNldCgibGFiZWxzX2NvbG9ycyIsIHZhbHVlID0gdGlwX2NvbG9ycykKCnBhcihtYXIgPSBjKDUsIDgsIDQsIDE1KSkKcGxvdChkZW5kX2NvbG9yZWQsIG1haW4gPSAiQ2x1c3RlcmVkIGJ5IG9yZF9saWZlLCBDb2xvcmVkIGJ5IEdUREIgRmFtaWx5IiwgaG9yaXogPSBUUlVFKQoKbGVnZW5kKCJ0b3ByaWdodCIsIGxlZ2VuZCA9IHVuaXF1ZShncm91cF92ZWN0b3IpLAogICAgICAgZmlsbCA9IGFzLm51bWVyaWMoYXMuZmFjdG9yKHVuaXF1ZShncm91cF92ZWN0b3IpKSksIGJvcmRlciA9IE5BLCBidHkgPSAibiIpCgoKCiMgNC4gQ29sb3IgdGhlIGJyYW5jaGVzIG9yIGxhYmVscwpkZW5kX2NvbG9yZWQgPC0gZGVuZCAlPiUKICBzZXQoImxhYmVsc19jb2xvcnMiLCB2YWx1ZSA9IGFzLm51bWVyaWMoYXMuZmFjdG9yKGdyb3VwX3ZlY3RvcikpKSMgJT4lCiAgI3NldCgiYnJhbmNoZXNfa19jb2xvciIsIGsgPSBsZW5ndGgodW5pcXVlKGdyb3VwX3ZlY3RvcikpKSAgIyBvcHRpb25hbAoKCnBhcihtYXIgPSBjKDUsIDgsIDQsIDE1KSkgICMgYWRqdXN0IGFzIG5lZWRlZApwbG90KGFzLmRlbmRyb2dyYW0oZGVuZF9jb2xvcmVkKSwKICAgICBtYWluID0gIldhcmQuRCBDbHVzdGVyaW5nIG9mIDBBIEZsYW5rcyBpbiBQaGFnZXMgYnkgSG9zdCIsCiAgICAgeGxhYiA9ICJIZWlnaHQiLCB5bGFiID0gIkNsdXN0ZXIiLAogICAgIHN1YiA9ICIiLCBob3JpeiA9IFRSVUUpCgpgYGAKCmBgYHtyfQpsaWJyYXJ5KHZlZ2FuKQpsaWJyYXJ5KGdncGxvdDIpCgojIDEuIENvbXB1dGUgQnJheS1DdXJ0aXMgZGlzdGFuY2UKYnJheV9kaXN0LnBoeSA8LSB2ZWdkaXN0KHQuYmFjaWxsaS5mYW0sIG1ldGhvZCA9ICJicmF5IikKCiMgMi4gUnVuIE5NRFMKbm1kc19yZXN1bHQgPC0gbWV0YU1EUyhicmF5X2Rpc3QucGh5LCBrID0gMiwgdHJ5bWF4ID0gMTAwKQoKIyAzLiBFeHRyYWN0IE5NRFMgY29vcmRpbmF0ZXMKbm1kc19wb2ludHMgPC0gYXMuZGF0YS5mcmFtZShubWRzX3Jlc3VsdCRwb2ludHMpCm5tZHNfcG9pbnRzJFNhbXBsZUlEIDwtIHJvd25hbWVzKG5tZHNfcG9pbnRzKQoKCm1ldGEgPC0gc2VsZWN0KGFsbC5jbHVzdC5iYWNpbGwsIGhvc3RzcGVjX3BoYWdlX3Nwb3IsIGZhbV9saWZlLCBzcG9ydWxhdGlvbiwgbGlmZXN0eWxlLCBob3N0X3BoeWxhLG5ld2d0ZGJfUGh5bHVtLCBndGRiX2YsIHBoYWdlX3R5cGUsIG5ld2d0ZGJfT3JkZXIsIG5ld2d0ZGJfQ2xhc3MpCgptZXRhIDwtIHN1YnNldChtZXRhLCBtZXRhJG5ld2d0ZGJfUGh5bHVtPT0iQmFjaWxsb3RhIikKbWV0YSA8LSB1bmlxdWUobWV0YSkKCiMgNC4gSWYgeW91IGhhdmUgbWV0YWRhdGEgKGUuZy4sIGdyb3VwaW5ncyksIG1lcmdlIGl0IGhlcmUKIyBBc3N1bWluZyBgbWV0YWAgaXMgYSBkYXRhLmZyYW1lIHdpdGggc2FtcGxlIG1ldGFkYXRhIGFuZCBtYXRjaGluZyByb3duYW1lcwogbm1kc19wb2ludHMgPC0gbWVyZ2Uobm1kc19wb2ludHMsIG1ldGEsIGJ5LnggPSAiU2FtcGxlSUQiLCBieS55ID0gImZhbV9saWZlIikKCiMgNS4gUGxvdApnZ3Bsb3Qobm1kc19wb2ludHMsIGFlcyh4ID0gTURTMSwgeSA9IE1EUzIsIGNvbG9yPSBuZXdndGRiX09yZGVyLCBzaGFwZT1zcG9ydWxhdGlvbikpICsKICBnZW9tX3BvaW50KHNpemUgPSAzKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlID0gIk5NRFMgb2YgQnJheS1DdXJ0aXMgRGlzdGFuY2VzIiwgeCA9ICJOTURTMSIsIHkgPSAiTk1EUzIiKSAKIAogCmdncGxvdChubWRzX3BvaW50cywgYWVzKHggPSBNRFMxLCB5ID0gTURTMiwgY29sb3I9IG5ld2d0ZGJfT3JkZXIsIHNoYXBlPXBoYWdlX3R5cGUpKSArCiAgZ2VvbV9wb2ludChzaXplID0gNCkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh0aXRsZSA9ICJOTURTIG9mIEphY2NhcmQgRGlzdGFuY2VzIG9mIDBBIGJveGVzIG9mIEJhY2lsbG90YSBwaGFnZXMiLCB4ID0gIk5NRFMxIiwgeSA9ICJOTURTMiIpCgojZ2dzYXZlKGhlcmUoImxhYl9wcmVzL0phY2NhcmRfMEFCYWNpbGxpb3RhX05NRFMucG5nIiksIGhlaWdodCA9IDksIHdpZHRoPTkpCgoKZ2dwbG90KG5tZHNfcG9pbnRzLCBhZXMoeCA9IE1EUzEsIHkgPSBNRFMyLCBjb2xvcj0gbmV3Z3RkYl9PcmRlciwgc2hhcGU9cGhhZ2VfdHlwZSkpICsKICBnZW9tX3BvaW50KHNpemUgPSA0KSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlID0gIk5NRFMgb2YgQnJheSBEaXN0YW5jZXMgb2YgMEEgYm94ZXMgb2YgQmFjaWxsb3RhIHBoYWdlcyIsIHggPSAiTk1EUzEiLCB5ID0gIk5NRFMyIikKCgoKZ2dzYXZlKGhlcmUoImxhYl9wcmVzL0JyYXlfMEFCYWNpbGxpb3RhX05NRFMucG5nIiksIGhlaWdodCA9IDksIHdpZHRoPTkpCgpgYGAKCgoKCgpgYGB7cn0KbGlicmFyeSh2ZWdhbikKbGlicmFyeShnZ3Bsb3QyKQoKIyAxLiBDb21wdXRlIEJyYXktQ3VydGlzIGRpc3RhbmNlCmJyYXlfZGlzdC5waHkgPC0gdmVnZGlzdCh0LnN1cGVyLCBtZXRob2QgPSAiYnJheSIpCgojIDIuIFJ1biBOTURTCm5tZHNfcmVzdWx0IDwtIG1ldGFNRFMoYnJheV9kaXN0LnBoeSwgayA9IDIsIHRyeW1heCA9IDEwMCkKCiMgMy4gRXh0cmFjdCBOTURTIGNvb3JkaW5hdGVzCm5tZHNfcG9pbnRzIDwtIGFzLmRhdGEuZnJhbWUobm1kc19yZXN1bHQkcG9pbnRzKQpubWRzX3BvaW50cyRTYW1wbGVJRCA8LSByb3duYW1lcyhubWRzX3BvaW50cykKCgptZXRhIDwtIHNlbGVjdChhbGwsIGhvc3RzcGVjX3BoYWdlX3Nwb3IsIHNwb3J1bGF0aW9uLCBsaWZlc3R5bGUsIGhvc3RfcGh5bGEsbmV3Z3RkYl9QaHlsdW0pCm1ldGEgPC0gdW5pcXVlKG1ldGEpCgojIDQuIElmIHlvdSBoYXZlIG1ldGFkYXRhIChlLmcuLCBncm91cGluZ3MpLCBtZXJnZSBpdCBoZXJlCiMgQXNzdW1pbmcgYG1ldGFgIGlzIGEgZGF0YS5mcmFtZSB3aXRoIHNhbXBsZSBtZXRhZGF0YSBhbmQgbWF0Y2hpbmcgcm93bmFtZXMKIG5tZHNfcG9pbnRzIDwtIG1lcmdlKG5tZHNfcG9pbnRzLCBtZXRhLCBieS54ID0gIlNhbXBsZUlEIiwgYnkueSA9ICJob3N0c3BlY19waGFnZV9zcG9yIikKCiMgNS4gUGxvdApnZ3Bsb3Qobm1kc19wb2ludHMsIGFlcyh4ID0gTURTMSwgeSA9IE1EUzIsIGNvbG9yPW5ld2d0ZGJfUGh5bHVtLCBzaGFwZT1saWZlc3R5bGUpKSArCiAgZ2VvbV9wb2ludChzaXplID0gNSkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh0aXRsZSA9ICJOTURTIG9mIEJyYXktQ3VydGlzIERpc3RhbmNlcyIsIHggPSAiTk1EUzEiLCB5ID0gIk5NRFMyIikKCgpnZ3NhdmUoaGVyZSgibGFiX3ByZXMvTk1EU19QaHkwQV9icmF5LnBuZyIpLCBoZWlnaHQgPSA5LCB3aWR0aD05KQpgYGAKYGBge3J9CmxpYnJhcnkodmVnYW4pCmxpYnJhcnkoZ2dwbG90MikKCiMgMS4gQ29tcHV0ZSBCcmF5LUN1cnRpcyBkaXN0YW5jZQpicmF5X2Rpc3QucGh5IDwtIHZlZ2Rpc3QodC5zdXBlciwgbWV0aG9kID0gImphY2NhcmQiKQoKIyAyLiBSdW4gTk1EUwpubWRzX3Jlc3VsdCA8LSBtZXRhTURTKGJyYXlfZGlzdC5waHksIGsgPSAyLCB0cnltYXggPSAxMDApCgojIDMuIEV4dHJhY3QgTk1EUyBjb29yZGluYXRlcwpubWRzX3BvaW50cyA8LSBhcy5kYXRhLmZyYW1lKG5tZHNfcmVzdWx0JHBvaW50cykKbm1kc19wb2ludHMkU2FtcGxlSUQgPC0gcm93bmFtZXMobm1kc19wb2ludHMpCgoKbWV0YSA8LSBzZWxlY3QoYWxsLCBob3N0c3BlY19waGFnZV9zcG9yLCBzcG9ydWxhdGlvbiwgbGlmZXN0eWxlLCBob3N0X3BoeWxhLG5ld2d0ZGJfUGh5bHVtKQptZXRhIDwtIHVuaXF1ZShtZXRhKQoKIyA0LiBJZiB5b3UgaGF2ZSBtZXRhZGF0YSAoZS5nLiwgZ3JvdXBpbmdzKSwgbWVyZ2UgaXQgaGVyZQojIEFzc3VtaW5nIGBtZXRhYCBpcyBhIGRhdGEuZnJhbWUgd2l0aCBzYW1wbGUgbWV0YWRhdGEgYW5kIG1hdGNoaW5nIHJvd25hbWVzCiBubWRzX3BvaW50cyA8LSBtZXJnZShubWRzX3BvaW50cywgbWV0YSwgYnkueCA9ICJTYW1wbGVJRCIsIGJ5LnkgPSAiaG9zdHNwZWNfcGhhZ2Vfc3BvciIpCgojIDUuIFBsb3QKZ2dwbG90KG5tZHNfcG9pbnRzLCBhZXMoeCA9IE1EUzEsIHkgPSBNRFMyLCBjb2xvcj1uZXdndGRiX1BoeWx1bSwgc2hhcGU9bGlmZXN0eWxlKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDUpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGUgPSAiTk1EUyBvZiBKYWNjYXJkIERpc3RhbmNlcyIsIHggPSAiTk1EUzEiLCB5ID0gIk5NRFMyIikKCmdnc2F2ZShoZXJlKCJsYWJfcHJlcy9OTURTX1BoeTBBX2phY2NhcmQucG5nIiksIGhlaWdodCA9IDksIHdpZHRoPTEwKQpgYGAKCgoKCgpgYGB7cn0KCgpsaWJyYXJ5KHBoeWxvc2VxKQoKb3R1IDwtIG90dV90YWJsZSh0LnN1cGVyLCB0YXhhX2FyZV9yb3dzID0gRkFMU0UpCgpzYW1wbGVfbmFtZXMob3R1KQoKCnNhbXBsZV9kZiA8LSBwaGFnZQoKcm93bmFtZXMoc2FtcGxlX2RmKSA8LSBzYW1wbGVfZGYkQWNjZXNzaW9uCnNhbXBsZV9kYXRhX29iaiA8LSBzYW1wbGVfZGF0YShzYW1wbGVfZGYpCgoKCnBzIDwtIHBoeWxvc2VxKG90dV90YWJsZShvdHUpLCBzYW1wbGVfZGF0YShzYW1wbGVfZGF0YV9vYmopKQoKCiMgQnJheS1DdXJ0aXMKb3JkX2JjIDwtIG9yZGluYXRlKHBzLCBtZXRob2QgPSAiUENvQSIsIGRpc3RhbmNlID0gImJyYXkiKQoKIyBKYWNjYXJkIChiaW5hcnkgcHJlc2VuY2UvYWJzZW5jZSkKb3JkX2phY2NhcmQgPC0gb3JkaW5hdGUocHMsIG1ldGhvZCA9ICJQQ29BIiwgZGlzdGFuY2UgPSAiamFjY2FyZCIpCgoKcGxvdF9vcmRpbmF0aW9uKHBzLCBvcmRfYmMsIGNvbG9yPSJob3N0X3BoYWdlX3Nwb3IiKSArCiAgZ2d0aXRsZSgiUGNPQSAoQnJheS1DdXJ0aXMpIikgKwogIHRoZW1lX21pbmltYWwoKQoKcGxvdF9vcmRpbmF0aW9uKHBzLCBvcmRfamFjY2FyZCwgY29sb3I9Im5ld2d0ZGJfQ2xhc3MiKSArCiAgZ2d0aXRsZSgiUGNPQSAoQnJheS1DdXJ0aXMpIikgKwogIHRoZW1lX21pbmltYWwoKQoKYGBgCgoKCgpsaWJyYXJ5KHBoeWxvc2VxKQoKb3R1IDwtIG90dV90YWJsZSh0LmJhY2lsbGkucGhhZ2UsIHRheGFfYXJlX3Jvd3MgPSBGQUxTRSkKCiNzYW1wbGVfbmFtZXMob3R1KQoKCnNhbXBsZV9kZiA8LSBwaGFnZQoKcm93bmFtZXMoc2FtcGxlX2RmKSA8LSBzYW1wbGVfZGYkQWNjZXNzaW9uCnNhbXBsZV9kYXRhX29iaiA8LSBzYW1wbGVfZGF0YShzYW1wbGVfZGYpCgoKCnBzIDwtIHBoeWxvc2VxKG90dV90YWJsZShvdHUpLCBzYW1wbGVfZGF0YShzYW1wbGVfZGF0YV9vYmopKQoKCiMgQnJheS1DdXJ0aXMKb3JkX2JjIDwtIG9yZGluYXRlKHBzLCBtZXRob2QgPSAiUENvQSIsIGRpc3RhbmNlID0gImJyYXkiKQoKIyBKYWNjYXJkIChiaW5hcnkgcHJlc2VuY2UvYWJzZW5jZSkKb3JkX2phY2NhcmQgPC0gb3JkaW5hdGUocHMsIG1ldGhvZCA9ICJQQ29BIiwgZGlzdGFuY2UgPSAiamFjY2FyZCIpCgoKcGxvdF9vcmRpbmF0aW9uKHBzLCBvcmRfYmMsIGNvbG9yPSJob3N0X3BoYWdlX3Nwb3IiKSArCiAgZ2d0aXRsZSgiUGNPQSAoQnJheS1DdXJ0aXMpIikgKwogIHRoZW1lX21pbmltYWwoKQoKcGxvdF9vcmRpbmF0aW9uKHBzLCBvcmRfamFjY2FyZCwgY29sb3I9Im5ld2d0ZGJfQ2xhc3MiKSArCiAgZ2d0aXRsZSgiUGNPQSAoQnJheS1DdXJ0aXMpIikgKwogIHRoZW1lX21pbmltYWwoKQoKCgoKIyMjIyBNQVlCRSBBTFNPIExPTCBJREsKCgoKdW5pcXVlLjMwIDwtIGFzLmRhdGEuZnJhbWUodW5pcXVlKGFsbC5oaXRzJENvbnRleHQpKQoKdW5pcXVlLjMwJGJveElEIDwtIHJvdy5uYW1lcyh1bmlxdWUuMzApCmNvbG5hbWVzKHVuaXF1ZS4zMCkgPC0gYygiQ29udGV4dCIsICJib3hJRCIpCnVuaXF1ZS4zMCRib3hDbHVzdGVyIDwtIHBhc3RlMCgiQm94XyIsIHVuaXF1ZS4zMCRib3hJRCkKCmFsbC5oaXRzIDwtIG1lcmdlKGFsbC5oaXRzLCB1bmlxdWUuMzAsIGJ5PSJDb250ZXh0IiwgYWxsLng9VFJVRSwgYWxsLnk9VFJVRSkKCiNib3guZGl2IDwtIGFsbC5oaXRzWyxjKDE6MywxMiwxNSwxNywzOCwzOSw0Niw0OTo1NildCgojIENvbnN0cnVjdCBGQVNUQS1mb3JtYXR0ZWQgbGluZXMKZmFzdGFfbGluZXMgPC0gcGFzdGUwKCI+IiwgdW5pcXVlLjMwJGJveENsdXN0ZXIsICJcbiIsIHVuaXF1ZS4zMCRDb250ZXh0KQojZmFzdGFfbGluZXMKIyBXcml0ZSB0byBmaWxlCndyaXRlTGluZXMoZmFzdGFfbGluZXMsIGhlcmUoImRhdGEvaW5waGFyZWRfZGIvMTRBcHIyMDI1XzBBVW5pcXVlLmZuYSIpKQogICAgIAoKCgpgYGB7cn0KY2x1c3QgPC0gcmVhZC5jc3YoaGVyZSgiZGF0YS9pbnBoYXJlZF9kYi8wYV9jbHVzdGVycy9uZXN0ZWQvMTRBcHIyMDI1XzBBX25lc3RlZC5jc3YiKSwgcm93Lm5hbWVzPTEpCmBgYAoKCgojIyMgbW9yZSBpZGsgbG9sCgoKCmBgYHtyfQoKIyMjIG5tZHMgYW5ncnkgbWVtb3J5IHZlcnkgc2xvdwpzZXQuc2VlZCg0MikKbm1kcyA8LSBtZXRhTURTKGNsdXN0ZXJfdGF4YV9tYXRyaXgsIGRpc3RhbmNlID0gImJyYXkiLCBrID0gMiwgdHJ5bWF4ID0gMTAwKQoKbm1kc19wb2ludHMgPC0gYXMuZGF0YS5mcmFtZShubWRzJHBvaW50cykKbm1kc19wb2ludHMkQ2x1c3RlciA8LSByb3duYW1lcyhubWRzX3BvaW50cykKCmdncGxvdChubWRzX3BvaW50cywgYWVzKHggPSBNRFMxLCB5ID0gTURTMiwgbGFiZWwgPSBDbHVzdGVyKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMsIGNvbG9yID0gImRhcmtibHVlIikgKwogIGdlb21fdGV4dCh2anVzdCA9IC0wLjgpICsKICBsYWJzKHRpdGxlID0gIk5NRFMgb2YgRmxhbmtpbmcgUmVnaW9uIENsdXN0ZXJzIGJ5IFRheG9ub215IikgKwogIHRoZW1lX21pbmltYWwoKQoKCgpoYyA8LSBoY2x1c3QoYnJheV9kaXN0LCBtZXRob2QgPSAiYXZlcmFnZSIpICAjIFVzZSAiY29tcGxldGUiLCAid2FyZC5EIiwgZXRjLiBpZiBwcmVmZXJyZWQKcGxvdChoYywgbWFpbiA9ICJEZW5kcm9ncmFtIG9mIEZsYW5raW5nIENsdXN0ZXJzIGJ5IEhvc3QgQ29tcG9zaXRpb24iLAogICAgIHhsYWIgPSAiQ2x1c3RlciIsIHN1YiA9ICIiLCBoYW5nID0gLTEpCgoKYnJheV9kaXN0IDwtIHZlZ2Rpc3QoY2x1c3Rlcl90YXhhX21hdHJpeCwgbWV0aG9kID0gImJyYXkiKQpqYWNjYXJkX2Rpc3QgPC0gdmVnZGlzdChjbHVzdGVyX3RheGFfbWF0cml4LCBtZXRob2QgPSAiamFjY2FyZCIpCgpwY29hX3Jlc3VsdCA8LSBjbWRzY2FsZShqYWNjYXJkX2Rpc3QsIGVpZyA9IFRSVUUsIGsgPSAyKSAjIGsgc3BlY2lmaWVzIHRoZSBudW1iZXIgb2YgZGltZW5zaW9ucyB0byByZXRyaWV2ZQoKcGNvYV9zY29yZXMgPC0gYXMuZGF0YS5mcmFtZShwY29hX3Jlc3VsdCRwb2ludHMpCmNvbG5hbWVzKHBjb2Ffc2NvcmVzKSA8LSBjKCJQQ28xIiwgIlBDbzIiKSAjIFJlbmFtZSBjb2x1bW5zIGZvciBjbGFyaXR5CnBjb2FfZWlnZW52YWx1ZXMgPC0gcGNvYV9yZXN1bHQkZWlnCgpwY29hX3Njb3JlcyRHcm91cCA8LSBtZXRhZGF0YSRHcm91cAoKZ2dwbG90KHBjb2Ffc2NvcmVzLCBhZXMoeCA9IFBDbzEsIHkgPSBQQ28yLCBjb2xvciA9IEdyb3VwKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsKICBzdGF0X2VsbGlwc2UoKSArICMgQWRkIGNvbmZpZGVuY2UgZWxsaXBzZXMgZm9yIGdyb3VwcyAob3B0aW9uYWwpCiAgbGFicyh0aXRsZSA9ICJQQ29BIG9mIEphY2NhcmQgRGlzdGFuY2VzIiwKICAgICAgIHggPSBwYXN0ZTAoIlBDbzEgKCIsIHJvdW5kKHBjb2FfZWlnZW52YWx1ZXNbMV0vc3VtKHBjb2FfZWlnZW52YWx1ZXMpICogMTAwLCAyKSwgIiUpIiksCiAgICAgICB5ID0gcGFzdGUwKCJQQ28yICgiLCByb3VuZChwY29hX2VpZ2VudmFsdWVzWzJdL3N1bShwY29hX2VpZ2VudmFsdWVzKSAqIDEwMCwgMiksICIlKSIpKSArCiAgdGhlbWVfYncoKQoKCgpCZF9BU19vYi5vcmQubm1kcy5icmF5IDwtIG9yZGluYXRlKCwgbWV0aG9kPSJOTURTIiwgZGlzdGFuY2U9ImJyYXkiKQoKCkJkX0FTX2JyYXlwbG90PXBsb3Rfb3JkaW5hdGlvbihCZF9BU19vYi5wcm9wLCBCZF9BU19vYi5vcmQubm1kcy5icmF5LCBjb2xvcj0iQmRQb3MiLCBzaGFwZT0iVHlwZV9TaXRlX1llYXIiLCB0aXRsZT0iQnJheS1DdXJ0aXMgRGlzc2ltaWxhcml0eSIpKyAKICBnZW9tX3BvaW50KHNpemUgPSAzKSsgdGhlbWVfY2xhc3NpYygpK3RoZW1lKHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTIpKQoKCmBgYAoKCgoKCiMjIyBJREsgTE9MCgpgYGB7cn0KIyMjIGNoYXRHUFQgc3VnZ2VzdGlvbgpsaWJyYXJ5KERFQ0lQSEVSKQpzZXQuc2VlZCgxMjMpCiMgc3BlY2lmeSB0aGUgcGF0aCB0byB0aGUgRkFTVEEgZmlsZSAoaW4gcXVvdGVzKQpmYXMgPC0gaGVyZSgiZGF0YS9pbnBoYXJlZF9kYi8wYV9jbHVzdGVycy9uZXN0ZWQvMTRBcHIyMDI1XzBBXzgwc2ltLm91dCIpCgojIGxvYWQgdGhlIHNlcXVlbmNlcyBmcm9tIHRoZSBmaWxlCiMgY2hhbmdlICJETkEiIHRvICJSTkEiIG9yICJBQSIgYXMgbmVlZGVkCnNlcXMgPC0gcmVhZEROQVN0cmluZ1NldChmYXMpCgoKCmNkaGl0OTUgPC0gcmVhZC5jc3YoImRhdGEvaW5waGFyZWRfZGIvMGFfY2x1c3RlcnMvMTRBcHIyMDI1XzBBXzk1X2NsdXN0ZXJzLmNzdiIsIHJvdy5uYW1lcz0xKQoKZGlzdHMgPC0gRGlzdGFuY2VNYXRyaXgoc2VxcywgdHlwZSA9ICJkaXN0IiwgY29ycmVjdGlvbiA9ICJKdWtlcy1DYW50b3IiKQoKbGlicmFyeShmYXN0Y2x1c3RlcikKaGMgPC0gaGNsdXN0KGFzLmRpc3QoZGlzdHMpLCBtZXRob2QgPSAiYXZlcmFnZSIpCgojIyB0b28gbXVjaCBtZW1vcnkKIyMgaGMgPC0gaGNsdXN0KGFzLmRpc3QoZGlzdHMpLCBtZXRob2QgPSAiY29tcGxldGUiKSAgIyBvciAiYXZlcmFnZSIsICJ3YXJkLkQyIiwgZXRjLgoKY2x1c3RlcnMgPC0gQ2x1c3Rlcml6ZShzZXFzLAogICAgICAgICAgICAgICAgICAgICAgIGN1dG9mZiA9IDAuMSwKICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAib3ZlcmxhcCIsCiAgICAgICAgICAgICAgICAgICAgICAgaW5jbHVkZVRlcm1pbmFsR2FwcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIG1pbkNvdmVyYWdlID0gMC41LAogICAgICAgICAgICAgICAgICAgICAgIHByb2Nlc3NvcnMgPSBOVUxMKSAgIyBvciBOVUxMIGZvciBhdXRvCgpjbHVzdGVycyA8LSBjdXRyZWUoaGMsIGggPSAwLjEpICAjIE9yIHNldCBrID0gbnVtYmVyIG9mIGNsdXN0ZXJzCmBgYAoKCgoKCgoKYGBge3J9CgoKYGBgCgoKYGBge3J9CiMgbG9vayBhdCBzb21lIG9mIHRoZSBzZXF1ZW5jZXMgKG9wdGlvbmFsKQpzZXFzCgpjbHVzdDkwIDwtIENsdXN0ZXJpemUoc2VxcywKY3V0b2ZmPTAuMSwgIyA+PSA5MCUgc2ltaWxhcgptaW5Db3ZlcmFnZT0wLjUsICMgPiA1MCUgY292ZXJhZ2UKcHJvY2Vzc29ycz1OVUxMKSAjIHVzZSBhbGwgQ1BVcwoKY2x1c3QuOTAgPC0gY2x1c3Q5MAptYXgoY2x1c3QuOTApCnQgPC0gdGFibGUoY2x1c3QuOTApCgptZWFuKHQpCnRhaWwoc29ydCh0KSkgIyBiaWdnZXN0IGNsdXN0ZXJzCmBgYAoKCmBgYHtyfQpjbHVzdDc1IDwtIENsdXN0ZXJpemUoc2VxcywKY3V0b2ZmPTAuMjUsICMgPiA3NSUgc2ltaWxhcgptaW5Db3ZlcmFnZT0wLjUsICMgPiA1MCUgY292ZXJhZ2UKcHJvY2Vzc29ycz1OVUxMKSAjIHVzZSBhbGwgQ1BVcwoKY2x1c3QuNzUgPC0gY2x1c3Q3NQptYXgoY2x1c3QuNzUpCnQgPC0gdGFibGUoY2x1c3QuNzUpCgptZWFuKHQpCnRhaWwoc29ydCh0KSkgIyBiaWdnZXN0IGNsdXN0ZXJzCmBgYAoKYGBge3J9CmNsdXN0NTAgPC0gQ2x1c3Rlcml6ZShzZXFzLApjdXRvZmY9MC41LCAjID4gNTAlIHNpbWlsYXIKbWluQ292ZXJhZ2U9MC41LCAjID4gNTAlIGNvdmVyYWdlCnByb2Nlc3NvcnM9TlVMTCkgIyB1c2UgYWxsIENQVXMKCmNsdXN0LjUwIDwtIGNsdXN0NTAKbWF4KGNsdXN0LjUwKQp0IDwtIHRhYmxlKGNsdXN0LjUwKQoKbWVhbih0KQp0YWlsKHNvcnQodCkpICMgYmlnZ2VzdCBjbHVzdGVycwoKYGBgCgpgYGB7cn0KCmNsdXN0LjUwIDwtIGNsdXN0NTAKY2x1c3QuOTAgPC0gY2x1c3Q5MApjbHVzdC43NSA8LSBjbHVzdDc1Cgpjb2xuYW1lcyhjbHVzdC45MCkgPC0gYygiY2x1c3RlcjkwIikKY2x1c3QuOTAkYm94Q2x1c3RlciA8LSByb3cubmFtZXMoY2x1c3QuOTApCgpjb2xuYW1lcyhjbHVzdC43NSkgPC0gYygiY2x1c3Rlcjc1IikKY2x1c3QuNzUkYm94Q2x1c3RlciA8LSByb3cubmFtZXMoY2x1c3QuNzUpCgpjb2xuYW1lcyhjbHVzdC41MCkgPC0gYygiY2x1c3RlcjUwIikKY2x1c3QuNTAkYm94Q2x1c3RlciA8LSByb3cubmFtZXMoY2x1c3QuNTApCgpgYGAKCmBgYHtyfQpjbHVzdG5lc3Q5MC4yIDwtIENsdXN0ZXJpemUoc2VxcywKY3V0b2ZmPXNlcSgwLjUsIDAuMjUsIC0uMTApKSAjIHVzZSBhbGwgQ1BVcwoKY2x1c3RuZXN0NzUgPC0gQ2x1c3Rlcml6ZShzZXFzLApjdXRvZmY9c2VxKDAuNSwgMC4yNSwgMCkpICMgdXNlIGFsbCBDUFVzCgpjbHVzdG5lc3Q1MCA8LSBDbHVzdGVyaXplKHNlcXMsCmN1dG9mZj0wLjUpICMgdXNlIGFsbCBDUFVzCgoKCgpjbHVzdC5uZXN0IDwtIGNsdXN0bmVzdDkwCm1heChjbHVzdC5uZXN0JGNsdXN0ZXJfMF8zKQp0IDwtIHRhYmxlKGNsdXN0Ljc1KQoKbWVhbih0KQp0YWlsKHNvcnQodCkpICMgYmlnZ2VzdCBjbHVzdGVycwoKCmNsdXN0bmVzdC45MCA8LSBjbHVzdG5lc3Q5MApjbHVzdG5lc3QuNzUgPC0gY2x1c3RuZXN0NzUKY2x1c3RuZXN0LjUwIDwtIGNsdXN0bmVzdDUwCgoKY29sbmFtZXMoY2x1c3RuZXN0LjkwKSA8LSBjKCJjbHVzdGVyOTAiKQpjbHVzdG5lc3QuOTAkYm94Q2x1c3RlciA8LSByb3cubmFtZXMoY2x1c3RuZXN0LjkwKQoKY29sbmFtZXMoY2x1c3RuZXN0Ljc1KSA8LSBjKCJjbHVzdGVyNzUiKQpjbHVzdG5lc3QuNzUkYm94Q2x1c3RlciA8LSByb3cubmFtZXMoY2x1c3RuZXN0Ljc1KQoKY29sbmFtZXMoY2x1c3RuZXN0LjUwKSA8LSBjKCJjbHVzdGVyNTAiKQpjbHVzdG5lc3QuNTAkYm94Q2x1c3RlciA8LSByb3cubmFtZXMoY2x1c3RuZXN0LjUwKQpgYGAKCgpgYGB7cn0KdW5pcXVlLjMwLmNsdXN0cyA8LSBtZXJnZSh1bmlxdWUuMzAsIGNsdXN0bmVzdC45MCwgYnk9ImJveENsdXN0ZXIiLCBhbGwueD1UUlVFLCBhbGwueT1UUlVFKSAlPiUKICBtZXJnZShjbHVzdG5lc3QuNzUsIGJ5PSJib3hDbHVzdGVyIiwgYWxsLng9VFJVRSwgYWxsLnk9VFJVRSkgJT4lCiAgIG1lcmdlKGNsdXN0bmVzdC41MCwgYnk9ImJveENsdXN0ZXIiLCBhbGwueD1UUlVFLCBhbGwueT1UUlVFKQoKYm94LmRpdiA8LSBtZXJnZShhbGwuaGl0cywgdW5pcXVlLjMwLmNsdXN0cywgYnk9IkNvbnRleHQiLCBhbGwueD1UUlVFLCBhbGwueT1UUlVFKQoKIyNub3RlIHRoYXQgdW5pcXVlMzBjbHVzdHMgbWF5IE5PVCBiZSBwZXJmZWN0bHkgbmVzdGVkCgp1bmlxdWUuMzAudW5pIDwtIHVuaXF1ZSh1bmlxdWUuMzAuY2x1c3RzWyxjKDQ6NildKQpgYGAKCmBgYHtyfQoKYm94LmRpdjIgPC0gc2VsZWN0KGJveC5kaXYsIHBoYWdlLCBDb250ZXh0LCBCb3hfQ29udGlnLCBib3hJRCwgY2x1c3RlcjkwLCBjbHVzdGVyNzUsIGNsdXN0ZXI1MCwgSG9zdCwgZ3RkYl9mLCBmX3Nwb3IsIHByZWRpY3RlZF9sYWJlbCwgaG9zdF9waGFnZV9zcG9yLCBwaGFnZV90eXBlLCBzcG9ydWxhdGlvbiwgbmV3Z3RkYl9QaHlsdW0sIGhvc3RfcGh5bGEsIGxpZmVzdHlsZSkKCmBgYAoK